[virt-v2v: 4/4] Pull in upstream patches to remove echoe dependence
Matthew Booth
mdbooth at fedoraproject.org
Wed May 11 16:39:35 UTC 2011
commit 55697cb1ebd419b29bed0c47b4e4141040fce8e8
Author: Matthew Booth <mbooth at redhat.com>
Date: Wed May 11 17:36:18 2011 +0100
Pull in upstream patches to remove echoe dependence
virt-v2v-0.8.1-00-44eb9021-modified.patch | 9296 +++++++++++++++++++++++++++++
virt-v2v-0.8.1-01-e34a8c09.patch | 57 +
virt-v2v-0.8.1-02-fadb1929.patch | 111 +
virt-v2v.spec | 20 +-
4 files changed, 9478 insertions(+), 6 deletions(-)
---
diff --git a/virt-v2v-0.8.1-00-44eb9021-modified.patch b/virt-v2v-0.8.1-00-44eb9021-modified.patch
new file mode 100644
index 0000000..5f0b250
--- /dev/null
+++ b/virt-v2v-0.8.1-00-44eb9021-modified.patch
@@ -0,0 +1,9296 @@
+diff -ruN virt-v2v-v0.8.1/Build.PL virt-v2v-v0.8.1.new/Build.PL
+--- virt-v2v-v0.8.1/Build.PL 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/Build.PL 2011-05-11 17:20:21.000000000 +0100
+@@ -26,7 +26,7 @@
+ {
+ my $self = shift;
+
+- system($self->config('make'), '-C', 'p2v-image-builder') == 0
++ system($self->config('make'), '-C', 'p2v/image-builder') == 0
+ or return 1;
+ }
+
+@@ -243,7 +243,7 @@
+ dist_version_from => 'lib/Sys/VirtConvert.pm',
+ confdoc_files => [ 'v2v/virt-v2v.conf.pod' ],
+ install_path => { 'locale' => '/usr/local/share/locale' },
+- script_files => [ 'v2v/virt-v2v.pl', 'p2v-server/virt-p2v-server.pl' ],
++ script_files => [ 'v2v/virt-v2v.pl', 'p2v/server/virt-p2v-server.pl' ],
+ meta_add => {
+ resources => {
+ license => "http://www.gnu.org/licenses/gpl.html",
+diff -ruN virt-v2v-v0.8.1/ChangeLog virt-v2v-v0.8.1.new/ChangeLog
+--- virt-v2v-v0.8.1/ChangeLog 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/ChangeLog 2011-05-11 17:20:21.000000000 +0100
+@@ -1,3 +1,33 @@
++2011-05-10 Matthew Booth <mbooth at redhat.com>
++
++ * Build.PL, MANIFEST, p2v-image-builder/Makefile, {p2v-client =>
++ p2v/client}/.gitignore, {p2v-client => p2v/client}/Manifest,
++ {p2v-client => p2v/client}/Rakefile, {p2v-client =>
++ p2v/client}/bin/virt-p2v, {p2v-client =>
++ p2v/client}/lib/virt-p2v/blockdevice.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/connection.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/converter.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/gtk-queue.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/netdevice.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/ui/connect.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/ui/convert.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/ui/main.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/ui/network.rb, {p2v-client =>
++ p2v/client}/lib/virt-p2v/ui/p2v.ui, {p2v-client =>
++ p2v/client}/lib/virt-p2v/ui/success.rb, {p2v-image-builder =>
++ p2v/image-builder}/.gitignore, p2v/image-builder/Makefile,
++ {p2v-image-builder => p2v/image-builder}/common-install.ks,
++ {p2v-image-builder => p2v/image-builder}/common-manifest-post.ks,
++ {p2v-image-builder => p2v/image-builder}/common-minimizer.ks,
++ {p2v-image-builder => p2v/image-builder}/common-pkgs.ks,
++ {p2v-image-builder => p2v/image-builder}/common-post-nochroot.ks,
++ {p2v-image-builder => p2v/image-builder}/common-post.ks,
++ {p2v-image-builder => p2v/image-builder}/virt-p2v-image-builder,
++ {p2v-image-builder => p2v/image-builder}/virt-p2v-image.ks,
++ {p2v-server => p2v/server}/run-p2v-locally, {p2v-server =>
++ p2v/server}/virt-p2v-server.pl, virt-v2v.spec.PL: Give p2v its own
++ subdirectory
++
+ 2011-04-26 Matthew Booth <mbooth at redhat.com>
+
+ * lib/Sys/VirtConvert.pm: Bump version to 0.8.1
+diff -ruN virt-v2v-v0.8.1/MANIFEST virt-v2v-v0.8.1.new/MANIFEST
+--- virt-v2v-v0.8.1/MANIFEST 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/MANIFEST 2011-05-11 17:20:21.000000000 +0100
+@@ -27,33 +27,33 @@
+ MANIFEST.SKIP
+ META.yml
+ metadata-format.txt
+-p2v-client/bin/virt-p2v
+-p2v-client/lib/virt-p2v/blockdevice.rb
+-p2v-client/lib/virt-p2v/connection.rb
+-p2v-client/lib/virt-p2v/converter.rb
+-p2v-client/lib/virt-p2v/gtk-queue.rb
+-p2v-client/lib/virt-p2v/netdevice.rb
+-p2v-client/lib/virt-p2v/ui/connect.rb
+-p2v-client/lib/virt-p2v/ui/convert.rb
+-p2v-client/lib/virt-p2v/ui/main.rb
+-p2v-client/lib/virt-p2v/ui/network.rb
+-p2v-client/lib/virt-p2v/ui/p2v.ui
+-p2v-client/lib/virt-p2v/ui/success.rb
+-p2v-client/Manifest
+-p2v-client/Rakefile
+-p2v-client/virt-p2v.gemspec
+-p2v-image-builder/common-install.ks
+-p2v-image-builder/common-manifest-post.ks
+-p2v-image-builder/common-minimizer.ks
+-p2v-image-builder/common-pkgs.ks
+-p2v-image-builder/common-post-nochroot.ks
+-p2v-image-builder/common-post.ks
+-p2v-image-builder/Makefile
+-p2v-image-builder/version.ks
+-p2v-image-builder/virt-p2v-image-builder
+-p2v-image-builder/virt-p2v-image.ks
+-p2v-server/run-p2v-locally
+-p2v-server/virt-p2v-server.pl
++p2v/client/bin/virt-p2v
++p2v/client/lib/virt-p2v/blockdevice.rb
++p2v/client/lib/virt-p2v/connection.rb
++p2v/client/lib/virt-p2v/converter.rb
++p2v/client/lib/virt-p2v/gtk-queue.rb
++p2v/client/lib/virt-p2v/netdevice.rb
++p2v/client/lib/virt-p2v/ui/connect.rb
++p2v/client/lib/virt-p2v/ui/convert.rb
++p2v/client/lib/virt-p2v/ui/main.rb
++p2v/client/lib/virt-p2v/ui/network.rb
++p2v/client/lib/virt-p2v/ui/p2v.ui
++p2v/client/lib/virt-p2v/ui/success.rb
++p2v/client/Manifest
++p2v/client/Rakefile
++p2v/client/virt-p2v.gemspec
++p2v/image-builder/common-install.ks
++p2v/image-builder/common-manifest-post.ks
++p2v/image-builder/common-minimizer.ks
++p2v/image-builder/common-pkgs.ks
++p2v/image-builder/common-post-nochroot.ks
++p2v/image-builder/common-post.ks
++p2v/image-builder/Makefile
++p2v/image-builder/version.ks
++p2v/image-builder/virt-p2v-image-builder
++p2v/image-builder/virt-p2v-image.ks
++p2v/server/run-p2v-locally
++p2v/server/virt-p2v-server.pl
+ po/es.po
+ po/it.po
+ po/Makefile
+diff -ruN virt-v2v-v0.8.1/p2v/client/bin/virt-p2v virt-v2v-v0.8.1.new/p2v/client/bin/virt-p2v
+--- virt-v2v-v0.8.1/p2v/client/bin/virt-p2v 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/bin/virt-p2v 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,62 @@
++#!/usr/bin/env ruby
++
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'virt-p2v/ui/main'
++require 'virt-p2v/ui/network'
++require 'virt-p2v/ui/connect'
++require 'virt-p2v/ui/convert'
++require 'virt-p2v/ui/success'
++
++require 'virt-p2v/converter'
++require 'virt-p2v/netdevice'
++
++require 'gettext'
++
++include GetText
++
++bindtextdomain('virt-p2v')
++
++if Process.uid != 0
++ puts _("virt-p2v must be executed with root privileges.\n" +
++ "It is intended to be included in a custom Live image, not " +
++ "run from the command\nline.")
++ abort
++end
++
++converter = VirtP2V::Converter.new
++
++# Initialise the wizard UI
++ui = VirtP2V::UI::Main.new
++
++# Initialize wizard pages
++VirtP2V::UI::Network.init(ui)
++VirtP2V::UI::Connect.init(ui, converter)
++VirtP2V::UI::Convert.init(ui, converter)
++VirtP2V::UI::Success.init(ui)
++
++# Skip the network configuration screen if there is already an active network
++# connection
++VirtP2V::NetworkDevice.all_devices.each { |device|
++ if device.activated then
++ ui.active_page = 'server_win'
++ break
++ end
++}
++
++ui.show
++ui.main_loop
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/blockdevice.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/blockdevice.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/blockdevice.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/blockdevice.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,112 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++module VirtP2V
++
++class NoSuchDeviceError < StandardError; end
++
++class FixedBlockDevice
++ @@devices = {}
++
++ def self.all_devices
++ @@devices.values
++ end
++
++ def self.[](device)
++ raise NoSuchDeviceError unless @@devices.has_key?(device)
++
++ @@devices[device]
++ end
++
++ attr_reader :device
++
++ def initialize(device)
++ @device = device
++ @@devices[device] = self
++ end
++end
++
++class RemovableBlockDevice
++ @@devices = {}
++
++ def self.all_devices
++ @@devices.values
++ end
++
++ def self.[](device)
++ raise NoSuchDeviceError unless @@devices.has_key?(device)
++
++ @@devices[device]
++ end
++
++ attr_reader :device, :type
++
++ def initialize(device, type)
++ @device = device
++ @type = type
++
++ @@devices[device] = self
++ end
++end
++
++# Detect and instantiate all fixed and removable block devices in the system
++begin
++ # Look for block devices
++ # Specifically, we look for entries in /sys/block which have a device
++ # symlink and no entries in their slaves subdirectory
++ Dir.foreach('/sys/block') { |dev|
++ next if dev == '.' || dev == '..'
++
++ # Skip if there's no device link
++ next unless File.exists?("/sys/block/#{dev}/device")
++
++ # Skip if the slaves subdirectory contains anything other than . and
++ # ..
++ begin
++ next if Dir.entries("/sys/block/#{dev}/slaves").length > 2
++ rescue Errno::ENOENT => ex
++ # This shouldn't happen, but if it did I guess it would mean
++ # there are no slave devices
++ end
++
++ # We've got a real block device. Check if it's removable or not
++ File.open("/sys/block/#{dev}/removable") { |fd|
++ removable = fd.gets.chomp
++ if removable == "0" then
++ FixedBlockDevice.new(dev)
++ else
++ # Look in device/modalias to work out what kind of removable
++ # device this is
++ type = File.open(
++ "/sys/block/#{dev}/device/modalias") \
++ { |modalias_f|
++ modalias = modalias_f.gets.chomp
++ if modalias =~ /floppy/ then
++ 'floppy'
++ elsif modalias =~ /cdrom/ then
++ 'cdrom'
++ else
++ # We don't know what this is, ignore it
++ end
++ }
++
++ RemovableBlockDevice.new(dev, type) unless type.nil?
++ end
++ }
++ }
++end
++
++end
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/connection.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/connection.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/connection.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/connection.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,320 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'gettext'
++require 'rubygems'
++require 'net/ssh'
++require 'thread'
++require 'yaml'
++
++require 'virt-p2v/gtk-queue'
++
++module VirtP2V
++
++class Connection
++ include GetText
++
++ attr_reader :connected
++
++ class InvalidHostnameError < StandardError; end
++ class InvalidCredentialsError < StandardError; end
++ class TransportError < StandardError; end
++ class NoP2VError < StandardError; end
++ class RemoteError < StandardError; end
++ class ProtocolError < StandardError; end
++ class NotConnectedError < StandardError; end
++
++ def on_connect(&cb)
++ @connection_listeners << cb
++ end
++
++ def initialize(hostname, username, password, &cb)
++ @mutex = Mutex.new
++ @connection_listeners = []
++
++ # Always send our version number on connection
++ @connection_listeners << Proc.new { |cb|
++ self.version { |result| cb.call(result) }
++ }
++
++ run(cb) {
++ error = nil
++ begin
++ @ssh = Net::SSH.start(hostname, username, :password => password)
++ rescue SocketError, Errno::EHOSTUNREACH => ex
++ raise InvalidHostnameError
++ raise ex
++ rescue Net::SSH::AuthenticationFailed => ex
++ raise InvalidCredentialsError
++ raise ex
++ end
++
++ @buffer = ""
++ @connected = false
++
++ Gtk.queue { cb.call(true) }
++ }
++ end
++
++ def connect(&cb)
++ run(cb) {
++ @ch = @ssh.open_channel do |ch|
++ ch.exec("virt-p2v-server") do |ch, success|
++ raise RemoteError,
++ "could not execute a remote command" unless success
++
++ ch.on_data do |ch, data|
++ @buffer << data
++ end
++
++ # If we get anything on stderr, raise it as a RemoteError
++ ch.on_extended_data do |ch, type, data|
++ close
++ raise RemoteError, data
++ end
++
++ # Clean up local resources if we get eof from the other end
++ ch.on_eof do |ch|
++ close
++ end
++
++ @connected = true
++ end
++
++ end
++
++ # Wait until we're connected
++ @ssh.loop do
++ !@connected
++ end
++
++ i = 0;
++ listener_result = lambda { |result|
++ if result.kind_of?(Exception)
++ cb.call(result)
++ else
++ i += 1
++ if i == @connection_listeners.length
++ cb.call(true)
++ else
++ Gtk.queue {
++ @connection_listeners[i].call(listener_result)
++ }
++ end
++ end
++ }
++ Gtk.queue { @connection_listeners[0].call(listener_result) }
++ }
++ end
++
++ def close
++ @connected = false
++ @buffer = ""
++ @ch.close
++ end
++
++ def version(&cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ @ch.send_data("VERSION 0\n")
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def lang(lang, &cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ @ch.send_data("LANG #{lang}\n")
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def metadata(meta, &cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ payload = YAML::dump(meta)
++ @ch.send_data("METADATA #{payload.length}\n");
++ @ch.send_data(payload)
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def path(length, path, &cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ @ch.send_data("PATH #{length} #{path}\n")
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def convert(&cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ @ch.send_data("CONVERT\n")
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def list_profiles(&cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ @ch.send_data("LIST_PROFILES\n")
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def set_profile(profile, &cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ @ch.send_data("SET_PROFILE #{profile}\n")
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def container(type, &cb)
++ raise NotConnectedError unless @connected
++
++ run(cb) {
++ @ch.send_data("CONTAINER #{type}\n")
++ result = parse_return
++
++ Gtk.queue { cb.call(result) }
++ }
++ end
++
++ def send_data(io, length, progress, &completion)
++ raise NotConnectedError unless @connected
++
++ run(completion) {
++ @ch.send_data("DATA #{length}\n")
++ total = 0
++ buffer = ''
++ begin
++ # This loop is in the habit of hanging in Net::SSH when sending
++ # a chunk larger than about 2M. Putting the 1 second wait
++ # timeout here kickstarts it if it stops.
++ @ssh.loop(1) {
++ if io.eof? || total == length then
++ false
++ else
++ if @ch.remote_window_size > 0 then
++ out = length - total
++ out = @ch.remote_window_size \
++ if out > @ch.remote_window_size
++
++ io.read(out, buffer)
++ @ch.send_data(buffer)
++
++ total += buffer.length
++
++ # Send a progress callback
++ Gtk.queue { progress.call(total) }
++ end
++
++ true
++ end
++ }
++ rescue => ex
++ Gtk.queue { completion.call(ex) }
++ end
++
++ result = parse_return
++
++ Gtk.queue { completion.call(result) }
++ }
++ end
++
++ private
++
++ def run(cb)
++ # Run the given block in a new thread
++ t = Thread.new {
++ begin
++ # We can't run more than 1 command simultaneously
++ @mutex.synchronize { yield }
++ rescue => ex
++ # Deliver exceptions to the caller, then re-raise them
++ Gtk.queue { cb.call(ex) }
++ raise ex
++ end
++ }
++ t.priority = 1
++ end
++
++ # Return a single line of output from the remote server
++ def readline
++ # Run the event loop until the buffer contains a newline
++ index = nil
++ @ssh.loop do
++ if !@ch.eof? then
++ index = @buffer.index("\n")
++ index.nil?
++ else
++ close
++ raise RemoteError, _('Server closed connection unexpectedly')
++ end
++ end
++
++ # Remove the line from the buffer and return it with the trailing
++ # newline removed
++ @buffer.slice!(0..index).chomp
++ end
++
++ def parse_return
++ line = readline
++ line =~ /^(OK|ERROR|LIST)(?:\s(.*))?$/ or
++ raise ProtocolError, "Invalid server response: #{line}"
++
++ return true if $~[1] == 'OK'
++ if $~[1] == 'ERROR' then
++ close
++ raise RemoteError, $~[2]
++ end
++
++ # LIST response. Get the number of items, and read that many lines
++ n = Integer($~[2])
++ ret = []
++ while n > 0 do
++ n -= 1
++ ret.push(readline)
++ end
++
++ ret
++ end
++end
++
++end
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/converter.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/converter.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/converter.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/converter.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,218 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'gettext'
++require 'rexml/document'
++include REXML
++
++require 'virt-p2v/netdevice'
++require 'virt-p2v/blockdevice'
++
++module VirtP2V
++
++# NIC
++# hostname
++# username
++# password
++
++# 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
++
++class Converter
++ include GetText
++
++ attr_accessor :profile, :name, :cpus, :memory, :arch
++ attr_reader :features, :disks, :removables, :nics
++
++ attr_reader :connection
++
++ def on_connection(&cb)
++ @connection_listeners << cb
++ end
++
++ def connection=(connection)
++ @connection = connection
++ @connection_listeners.each { |cb|
++ cb.call(connection)
++ }
++ end
++
++ 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|
++ status.call(_('Converting'))
++ @connection.convert(&cb)
++ }
++ ], completion)
++ end
++
++ private
++
++ def initialize()
++ @profile = nil
++ @connection = nil
++ @connection_listeners = []
++
++ # 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 `hwloc-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 = []
++ end
++
++ def disk(dev, status, progress, completion)
++ path = "/dev/#{dev}"
++ # XXX: No error checking of blockdev execution
++ size = Integer(`blockdev --getsize64 #{path}`.chomp)
++ 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 += 1
++ progress.call(dev, pc)
++ end
++ }, &cb)
++ }
++ ], completion)
++ end
++
++ 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
++
++ def meta
++ {
++ 'name' => @name,
++ 'cpus' => @cpus,
++ 'memory' => @memory,
++ 'arch' => @arch,
++ 'features' => @features,
++ 'disks' => @disks.map { |device|
++ {
++ 'device' => device,
++ 'path' => "/dev/#{device}",
++ 'is_block' => '1',
++ 'format' => 'raw'
++ }
++ },
++ '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
++end
++
++end
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/gtk-queue.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/gtk-queue.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/gtk-queue.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/gtk-queue.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,52 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++# This code is taken from:
++# http://ruby-gnome2.sourceforge.jp/hiki.cgi?tips_threads
++# The author of the above page is given as Tal Liron
++# The above page is distributed under the terms of the GNU FDL, although I
++# consider this code to be too trivial to be copyrightable
++
++require 'gtk2'
++require 'thread'
++
++module Gtk
++ GTK_PENDING_BLOCKS = []
++ GTK_PENDING_BLOCKS_LOCK = Mutex.new
++
++ def Gtk.queue &block
++ if Thread.current == Thread.main
++ block.call
++ else
++ GTK_PENDING_BLOCKS_LOCK.synchronize do
++ GTK_PENDING_BLOCKS << block
++ end
++ end
++ end
++
++ def Gtk.main_with_queue timeout
++ Gtk.timeout_add timeout do
++ GTK_PENDING_BLOCKS_LOCK.synchronize do
++ for block in GTK_PENDING_BLOCKS
++ block.call
++ end
++ GTK_PENDING_BLOCKS.clear
++ end
++ true
++ end
++ Gtk.main
++ end
++end
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/netdevice.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/netdevice.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/netdevice.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/netdevice.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,259 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'dbus'
++require 'gettext'
++
++module VirtP2V
++
++class NetworkDevice
++ include GetText
++
++ attr_reader :name, :mac, :connected, :activated, :state
++
++ # Some NetworkManager names, for convenience
++ CONNECTION = 'org.freedesktop.NetworkManagerSettings.Connection'.freeze
++ DEVICE = 'org.freedesktop.NetworkManager.Device'.freeze
++ NETWORKMANAGER = 'org.freedesktop.NetworkManager'.freeze
++ PROPERTIES = 'org.freedesktop.DBus.Properties'.freeze
++ SETTINGS = 'org.freedesktop.NetworkManagerSettings'.freeze
++ WIRED = 'org.freedesktop.NetworkManager.Device.Wired'.freeze
++
++ # NetworkManager device types
++ # http://projects.gnome.org/NetworkManager/developers/spec-08.html
++ TYPE_UNKNOWN = 0
++ TYPE_ETHERNET = 1
++ TYPE_WIFI = 2
++ TYPE_GSM = 3
++ TYPE_CDMA = 4
++
++ # NetworkManager device states
++ STATE_UNKNOWN = 0
++ STATE_UNMANAGED = 1
++ STATE_UNAVAILABLE = 2
++ STATE_DISCONNECTED = 3
++ STATE_PREPARE = 4
++ STATE_CONFIG = 5
++ STATE_NEED_AUTH = 6
++ STATE_IP_CONFIG = 7
++ STATE_ACTIVATED = 8
++ STATE_FAILED = 9
++
++ # Human readable descriptions of NetworkManager Device States
++ STATES = {
++ 0 => _('Unknown').freeze, # For completeness
++ 1 => _('Unmanaged').freeze, # For completeness
++ 2 => _('No cable connected').freeze,
++ 3 => _('Not connected').freeze,
++ 4 => _('Preparing to connect').freeze,
++ 5 => _('Configuring').freeze,
++ 6 => _('Waiting for authentication').freeze,
++ 7 => _('Obtaining an IP address').freeze,
++ 8 => _('Connected').freeze,
++ 9 => _('Connection failed').freeze
++ }.freeze
++
++ def initialize(obj, device, props)
++ device.default_iface = WIRED
++
++ @nm_obj = obj
++ @name = props.Get(DEVICE, 'Interface')[0]
++ @mac = props.Get(WIRED, 'HwAddress')[0]
++ state = props.Get(WIRED, 'State')[0]
++
++ # Lookup by name
++ @@devices[@name] = self
++
++ state_updated(state)
++
++ # Register a listener for state changes
++ device.on_signal('PropertiesChanged') { |props|
++ if props.has_key?('State') then
++ state_updated(props['State'])
++
++ # Notify registered state change handlers
++ @@listeners.each { |cb| cb.call(self) }
++ end
++ }
++ end
++
++ def self.all_devices()
++ @@devices.values
++ end
++
++ def self.add_listener(cb)
++ @@listeners.push(cb)
++ end
++
++ def self.[](name)
++ @@devices[name]
++ end
++
++ def activate(auto, ip, prefix, gateway, dns)
++ # Get an IP config dependent on whether @ip_address is IPv4 or IPv6
++ ip_config = auto ? get_config_auto :
++ ip.ipv4? ? get_config_ipv4() : get_config_ipv6()
++
++ # Create a new NetworkManager connection object
++ settings = @@nm_service.object(
++ '/org/freedesktop/NetworkManagerSettings')
++ settings.introspect()
++ settings.default_iface = SETTINGS
++
++ uuid = `uuidgen`.chomp
++ settings.AddConnection(
++ 'connection' => {
++ 'uuid' => uuid,
++ 'id' => 'P2V',
++ 'type' => '802-3-ethernet',
++ 'autoconnect' => false
++ },
++ '802-3-ethernet' => {},
++ 'ipv4' => ip_config['ipv4'],
++ 'ipv6' => ip_config['ipv6']
++ )
++
++ # Find the connection we just created
++ # XXX: There must be a better way to get this!
++ conn = settings.ListConnections()[0].each { |i|
++ conn = @@nm_service.object(i)
++ conn.introspect
++ conn.default_iface = CONNECTION
++
++ break i if conn.GetSettings()[0]['connection']['uuid'] == uuid
++ }
++
++ nm = @@nm_service.object('/org/freedesktop/NetworkManager')
++ nm.introspect
++ nm.default_iface = NETWORKMANAGER
++ nm.ActivateConnection('org.freedesktop.NetworkManagerSystemSettings',
++ conn, @nm_obj, '/')
++ end
++
++ private
++
++ def state_updated(state)
++ @connected = state > 2
++ @state = STATES[state]
++
++ if state == STATE_ACTIVATED then
++ @activated = true
++ elsif state == STATE_FAILED then
++ @activated = false
++ else
++ @activated = nil
++ end
++ end
++
++ def get_config_auto
++ {
++ 'ipv4' => {
++ 'method' => 'auto'
++ },
++ 'ipv6' => {
++ 'method' => 'ignore'
++ }
++ }
++ end
++
++ def ipv4_to_nm(ipaddr)
++ ipaddr.hton().unpack("I")[0]
++ end
++
++ def get_config_ipv4
++ addresses = [[ ipv4_to_nm(@ip_address), @ip_prefix,
++ ipv4_to_nm(@ip_gateway) ]]
++
++ dns = []
++ @ip_dns.each{ |ipaddr|
++ # Only use IPv4 DNS servers
++ next unless ipaddr.ipv4?
++ dns.push(ipv4_to_nm(ipaddr))
++ }
++
++ {
++ 'ipv4' => {
++ 'method' => 'manual',
++ 'addresses' => [ 'aau', addresses ],
++ 'dns' => [ 'au', dns ]
++ },
++ 'ipv6' => {
++ 'method' => 'ignore'
++ }
++ }
++ end
++
++ def ipv6_to_nm(ipaddr)
++ ipaddr.hton().unpack("c*")
++ end
++
++ def get_config_ipv6
++ dns = []
++ @ip_dns.each { |ipaddr|
++ # Only use IPv6 DNS servers
++ next unless ipaddr.ipv6?
++ dns.push(ipv6_to_nm(ipaddr))
++ }
++
++ {
++ 'ipv4' => {
++ 'method' => 'disabled'
++ },
++ 'ipv6' => {
++ 'method' => 'manual',
++ 'addresses' => [ 'a(ayu)', [[
++ ipv6_to_nm(@ip_address),
++ @ip_prefix
++ ]] ],
++ 'routes' => [ 'a(ayuayu)', [[
++ [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 0,
++ ipv6_to_nm(@ip_gateway), 1024
++ ]] ],
++ 'dns' => [ 'aay', dns ]
++ }
++ }
++ end
++
++ # Class initialization
++ begin
++ dbus = DBus::SystemBus.instance()
++ dbus.glibize()
++ @@nm_service = dbus.service(NETWORKMANAGER)
++
++ nm = @@nm_service.object('/org/freedesktop/NetworkManager')
++ nm.introspect
++ nm.default_iface = NETWORKMANAGER
++
++ @@devices = {}
++ nm.GetDevices()[0].each { |obj|
++ device = @@nm_service.object(obj)
++ device.introspect
++
++ props = device[PROPERTIES]
++ type = props.Get(DEVICE, 'DeviceType')[0]
++
++ # We only support ethernet devices
++ next unless type == TYPE_ETHERNET
++
++ # Constructor will add it to @@devices
++ self.new(obj, device, props)
++ }
++
++ @@listeners = []
++ end
++end
++
++end #module
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/connect.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/connect.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/connect.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/connect.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,179 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'gettext'
++require 'gtk2'
++
++require 'virt-p2v/connection'
++
++module VirtP2V::UI::Connect
++ include GetText
++
++ UI_STATE_INVALID = 0
++ UI_STATE_VALID = 1
++ UI_STATE_ACTIVATING = 2
++ UI_STATE_COMPLETE = 3
++
++ EV_HOSTNAME = 0
++ EV_USERNAME = 1
++ EV_PASSWORD = 2
++ EV_BUTTON = 3
++ EV_ACTIVATION = 4
++
++ def self.event(event, status)
++ case event
++ when EV_HOSTNAME
++ @hostname = status
++ when EV_USERNAME
++ @username = status
++ when EV_PASSWORD
++ @password = status
++ when EV_BUTTON, EV_ACTIVATION
++ # Persistent state not required
++ else
++ raise "Unexpected event: #{event}"
++ end
++
++ valid = @hostname && @username && @password
++
++ case @state
++ when UI_STATE_INVALID
++ set_state(UI_STATE_VALID) if valid
++ when UI_STATE_VALID
++ if !valid then
++ set_state(UI_STATE_INVALID)
++ elsif event == EV_BUTTON
++ set_state(UI_STATE_ACTIVATING)
++ end
++ when UI_STATE_ACTIVATING
++ # UI is disabled, so we shouldn't be getting any events other than
++ # EV_ACTIVATION
++ raise "Unexpected event: #{event}" unless event == EV_ACTIVATION
++
++ set_state(status ? UI_STATE_COMPLETE : UI_STATE_VALID)
++ else
++ raise "Unexpected UI state: #{@state}"
++ end
++ end
++
++ def self.init(ui, converter)
++ @hostname_ui = ui.get_object('server_hostname')
++ @username_ui = ui.get_object('server_username')
++ @password_ui = ui.get_object('server_password')
++ @connect_frame = ui.get_object('connect_frame')
++ @connect_button = ui.get_object('connect_button')
++ @connect_error = ui.get_object('connect_error')
++
++ ui.register_handler('server_hostname_changed',
++ method(:server_hostname_changed))
++ ui.register_handler('server_username_changed',
++ method(:server_username_changed))
++ ui.register_handler('server_password_changed',
++ method(:server_password_changed))
++ ui.register_handler('connect_button_clicked',
++ method(:connect_button_clicked))
++
++ @hostname = @hostname_ui.text.strip.length > 0
++ @username = @username_ui.text.strip.length > 0
++ @password = @password_ui.text.length > 0 # Allow spaces in passwords
++ @state = UI_STATE_INVALID
++
++ @ui = ui
++ @converter = converter
++ end
++
++ def self.set_state(state)
++ # Don't do anything if state hasn't changed
++ return if state == @state
++
++ case state
++ when UI_STATE_INVALID
++ @connect_frame.sensitive = true
++ @connect_button.sensitive = false
++
++ @state = UI_STATE_INVALID
++ when UI_STATE_VALID
++ @connect_frame.sensitive = true
++ @connect_button.sensitive = true
++
++ @state = UI_STATE_VALID
++ when UI_STATE_ACTIVATING
++ @connect_frame.sensitive = false
++ @connect_button.sensitive = false
++ @connect_error.text = ''
++
++ @state = UI_STATE_ACTIVATING
++ when UI_STATE_COMPLETE
++ # Activate the next page
++ @ui.active_page = 'conversion_win'
++
++ # ... then leave this one as we hope to find it if we come back here
++ set_state(UI_STATE_VALID)
++ else
++ raise "Attempt to set unexpected UI state: #{@state}"
++ end
++ end
++
++ def self.server_hostname_changed
++ event(EV_HOSTNAME, @hostname_ui.text.strip.length > 0)
++ end
++
++ def self.server_username_changed
++ event(EV_USERNAME, @username_ui.text.strip.length > 0)
++ end
++
++ def self.server_password_changed
++ event(EV_PASSWORD, @password_ui.text.length > 0)
++ end
++
++ def self.connect_button_clicked
++ event(EV_BUTTON, true)
++
++ hostname = @hostname_ui.text.strip
++ username = @username_ui.text.strip
++ password = @password_ui.text
++ connection = VirtP2V::Connection.new(hostname, username, password) \
++ { |result|
++ case result
++ when true
++ @converter.connection = connection
++ connection.connect { |result|
++ case result
++ when true
++ event(EV_ACTIVATION, true)
++ when VirtP2V::Connection::RemoteError
++ @connect_error.text = _('Failed to start ' +
++ 'virt-p2v-server on remote ' +
++ 'server')
++ event(EV_ACTIVATION, false)
++ else
++ @connect_error.text = result.message
++ event(EV_ACTIVATION, false)
++ end
++ }
++ when VirtP2V::Connection::InvalidHostnameError
++ @connect_error.text = _"Unable to connect to #{hostname}"
++ event(EV_ACTIVATION, false)
++ when VirtP2V::Connection::InvalidCredentialsError
++ @connect_error.text = _"Invalid username/password"
++ event(EV_ACTIVATION, false)
++ else
++ raise result
++ end
++ }
++ end
++
++end # module
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/convert.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/convert.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/convert.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/convert.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,422 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'gettext'
++require 'gtk2'
++
++require 'virt-p2v/blockdevice'
++require 'virt-p2v/netdevice'
++
++module VirtP2V::UI::Convert
++ include GetText
++
++ CONVERT_PROFILE_NAME = 0
++
++ CONVERT_NETWORK_CONVERT = 0
++ CONVERT_NETWORK_DEVICE = 1
++
++ CONVERT_FIXED_CONVERT = 0
++ CONVERT_FIXED_DEVICE = 1
++ CONVERT_FIXED_PROGRESS = 2
++
++ CONVERT_REMOVABLE_CONVERT = 0
++ CONVERT_REMOVABLE_DEVICE = 1
++ CONVERT_REMOVABLE_TYPE = 2
++
++ UI_STATE_INVALID = 0
++ UI_STATE_VALID = 1
++ UI_STATE_CONNECTING = 2
++ UI_STATE_CONVERTING = 3
++ UI_STATE_COMPLETE = 4
++
++ EV_VALID = 0
++ EV_BUTTON = 1
++ EV_CONNECTION = 2
++ EV_CONVERTED = 3
++
++ def self.init(ui, converter)
++ # ListStores
++ @profiles = ui.get_object('convert_profile_list')
++ @nics = ui.get_object('convert_network_list')
++ @fixeds = ui.get_object('convert_fixed_list')
++ @removables = ui.get_object('convert_removable_list')
++
++ # Widgets
++ @profile = ui.get_object('convert_profile')
++ @name = ui.get_object('convert_name')
++ @cpus = ui.get_object('convert_cpus')
++ @memory = ui.get_object('convert_memory')
++ @editable = ui.get_object('convert_editable')
++ @button = ui.get_object('convert_button')
++ @status = ui.get_object('convert_status')
++
++ # Get initial values from converter
++ @name.text = converter.name
++ @cpus.text = converter.cpus.to_s
++ @memory.text = (converter.memory / 1024 / 1024).to_s
++
++ # Populate profiles on connection
++ converter.on_connection { |conn|
++ conn.on_connect { |cb|
++ conn.list_profiles { |profiles|
++ cb.call(RuntimeError.new(_('Remote server does not ' +
++ 'define any profiles in ' +
++ '/etc/virt-v2v.conf'))) \
++ if profiles.kind_of?(Exception) or profiles.empty?
++
++ selected = @profile.active_iter
++ selected = selected[CONVERT_PROFILE_NAME] \
++ unless selected.nil?
++
++ @profiles.clear
++ profiles.each { |i|
++ profile = @profiles.append
++ profile[CONVERT_PROFILE_NAME] = i
++ @profile.active_iter = profile if i == selected
++ }
++
++ cb.call(true)
++ }
++ }
++ }
++
++ VirtP2V::FixedBlockDevice.all_devices.each { |dev|
++ fixed = @fixeds.append
++ fixed[CONVERT_FIXED_CONVERT] = true
++ fixed[CONVERT_FIXED_DEVICE] = dev.device
++ fixed[CONVERT_FIXED_PROGRESS] = 0
++ }
++
++ VirtP2V::RemovableBlockDevice.all_devices.each { |dev|
++ rem = @removables.append
++ rem[CONVERT_REMOVABLE_CONVERT] = true
++ rem[CONVERT_REMOVABLE_DEVICE] = dev.device
++ rem[CONVERT_REMOVABLE_TYPE] = dev.type
++ }
++
++ VirtP2V::NetworkDevice.all_devices.each { |dev|
++ nic = @nics.append
++ nic[CONVERT_NETWORK_CONVERT] = dev.connected
++ nic[CONVERT_NETWORK_DEVICE] = dev.name
++ }
++
++ # Event handlers
++ ui.register_handler('convert_profile_changed',
++ method(:update_values))
++ ui.register_handler('convert_name_changed',
++ method(:update_values))
++ ui.register_handler('convert_cpus_changed',
++ method(:convert_cpus_changed))
++ ui.register_handler('convert_memory_changed',
++ method(:convert_memory_changed))
++ ui.register_handler('convert_fixed_list_row_changed',
++ method(:convert_fixed_list_row_changed))
++ ui.register_handler('convert_removable_list_row_changed',
++ method(:update_values))
++ ui.register_handler('convert_network_list_row_changed',
++ method(:update_values))
++ ui.register_handler('convert_fixed_select_toggled',
++ method(:convert_fixed_select_toggled))
++ ui.register_handler('convert_removable_select_toggled',
++ method(:convert_removable_select_toggled))
++ ui.register_handler('convert_network_select_toggled',
++ method(:convert_network_select_toggled))
++ ui.register_handler('convert_button_clicked',
++ method(:convert_button_clicked))
++
++ @state = nil
++ set_state(UI_STATE_INVALID)
++ update_values
++
++ @ui = ui
++ @converter = converter
++ end
++
++ def self.event(event, status)
++ case @state
++ when UI_STATE_INVALID
++ case event
++ when EV_VALID
++ set_state(UI_STATE_VALID) if status
++ else
++ raise "Unexpected event: #{@state} #{event}"
++ end
++ when UI_STATE_VALID
++ case event
++ when EV_VALID
++ set_state(UI_STATE_INVALID) if !status
++ when EV_BUTTON
++ if @converter.connection.connected then
++ set_state(UI_STATE_CONVERTING)
++ convert
++ else
++ set_state(UI_STATE_CONNECTING)
++ reconnect
++ end
++ else
++ raise "Unexpected event: #{@state} #{event}"
++ end
++ when UI_STATE_CONNECTING
++ case event
++ when EV_CONNECTION
++ if status then
++ set_state(UI_STATE_CONVERTING)
++ convert
++ else
++ set_state(UI_STATE_VALID)
++ end
++ when EV_VALID
++ # update_values will be called when the profile list is cleared
++ # and repopulated during connection. Untidy, but ignore it.
++ else
++ raise "Unexpected event: #{@state} #{event}" \
++ unless event == EV_CONNECTION
++ end
++ when UI_STATE_CONVERTING
++ case event
++ when EV_CONVERTED
++ if status then
++ set_state(UI_STATE_COMPLETE)
++ else
++ set_state(UI_STATE_VALID)
++ end
++ when EV_VALID
++ # update_values will be called when the list stores are updated.
++ # Untidy, but ignore it
++ else
++ raise "Unexpected event: #{@state} #{event}"
++ end
++ else
++ raise "Unexpected UI state: #{@state}"
++ end
++ end
++
++ def self.set_state(state)
++ # Don't do anything if state hasn't changed
++ return if state == @state
++ @state = state
++
++ case @state
++ when UI_STATE_INVALID
++ @editable.sensitive = true
++ @button.sensitive = false
++ when UI_STATE_VALID
++ @editable.sensitive = true
++ @button.sensitive = true
++ when UI_STATE_CONNECTING
++ @status.text = _'Failed to start virt-p2v-server on remote server'
++ @editable.sensitive = false
++ @button.sensitive = false
++ when UI_STATE_CONVERTING
++ @editable.sensitive = false
++ @button.sensitive = false
++ when UI_STATE_COMPLETE
++ @ui.active_page = 'success_win'
++
++ # ... then leave this one as we hope to find it if we come back here
++ set_state(UI_STATE_VALID)
++ else
++ raise "Attempt to set unexpected UI state: #{@state}"
++ end
++ end
++
++ def self.convert
++ @converter.convert(
++ # status
++ lambda { |msg|
++ @status.text = msg
++ },
++ # progress
++ lambda { |dev, progress|
++ @fixeds.each { |model, path, iter|
++ next unless iter[CONVERT_FIXED_DEVICE] == dev
++
++ iter[CONVERT_FIXED_PROGRESS] = progress
++ break
++ }
++ }
++ ) { |result|
++ # N.B. Explicit test against true is required here, as result may be
++ # an Exception, which would also return true if evaluated alone
++ if result == true then
++ @status.text = ''
++ event(EV_CONVERTED, true)
++ else
++ @status.text = result.message
++ event(EV_CONVERTED, false)
++ end
++ }
++ end
++
++ def self.reconnect
++ @status.text = _('Reconnecting')
++ @converter.connection.connect { |result|
++ if result == true then
++ event(EV_CONNECTION, true)
++ else
++ @status.text =
++ _'Failed to start virt-p2v-server on remote server'
++ event(EV_CONNECTION, false)
++ end
++ }
++ end
++
++ def self.convert_fixed_list_row_changed(model, path, iter)
++ update_values
++ end
++
++ class InvalidUIState < StandardError; end
++
++ def self.update_values
++ valid = nil
++ begin
++ # Check there's a profile selected
++ profile = @profile.active_iter
++ raise InvalidUIState if profile.nil?
++ @converter.profile = profile[CONVERT_PROFILE_NAME]
++
++ # Check there's a name set
++ name = @name.text
++ raise InvalidUIState if name.nil? || name.strip.length == 0
++ @converter.name = name
++
++ # Check cpus and memory are set and numeric
++ cpus = @cpus.text
++ raise InvalidUIState if cpus.nil?
++ cpus = Integer(cpus) rescue nil
++ raise InvalidUIState if cpus.nil?
++ @converter.cpus = cpus
++
++ memory = @memory.text
++ raise InvalidUIState if memory.nil?
++ memory = Integer(memory) rescue nil
++ raise InvalidUIState if memory.nil?
++ @converter.memory = memory * 1024 * 1024
++
++ # Check that at least 1 fixed storage device is selected
++ fixed = false
++ @converter.disks.clear
++ @fixeds.each { |model, path, iter|
++ if iter[CONVERT_FIXED_CONVERT] then
++ fixed = true
++ @converter.disks << iter[CONVERT_FIXED_DEVICE]
++ end
++ }
++ raise InvalidUIState unless fixed
++
++ # Populate removables and nics, although these aren't required to be
++ # selected for the ui state to be valid
++ @converter.removables.clear
++ @removables.each { |model, path, iter|
++ if iter[CONVERT_REMOVABLE_CONVERT] then
++ @converter.removables << iter[CONVERT_REMOVABLE_DEVICE]
++ end
++ }
++ @converter.nics.clear
++ @nics.each { |model, path, iter|
++ if iter[CONVERT_NETWORK_CONVERT] then
++ @converter.nics << iter[CONVERT_NETWORK_DEVICE]
++ end
++ }
++ rescue InvalidUIState
++ valid = false
++ end
++ valid = true if valid.nil?
++
++ event(EV_VALID, valid)
++ end
++
++ def self.valid?
++ # Check there's a profile selected
++ profile = @profile.active_iter
++ return false if profile.nil?
++
++ # Check there's a name set
++ name = @name.text
++ return false if name.nil?
++ return false unless name.strip.length > 0
++
++ # Check cpus and memory are set and numeric
++ cpus = @cpus.text
++ return false if cpus.nil?
++ cpus = Integer(cpus) rescue nil
++ return false if cpus.nil?
++
++ memory = @memory.text
++ return false if memory.nil?
++ memory = Integer(memory) rescue nil
++ return false if memory.nil?
++
++ # Check that at least 1 fixed storage device is selected
++ fixed = false
++ @fixeds.each { |model, path, iter|
++ if iter[CONVERT_FIXED_CONVERT] then
++ fixed = true
++ break
++ end
++ }
++ return false unless fixed
++
++ return true
++ end
++
++ def self.convert_cpus_changed
++ check_numeric(@cpus)
++ end
++
++ def self.convert_memory_changed
++ check_numeric(@memory)
++ end
++
++ def self.check_numeric(widget)
++ value = widget.text
++ if value.nil? ? false : begin
++ value = Integer(value)
++ value > 0
++ rescue
++ false
++ end
++ then
++ widget.secondary_icon_name = nil
++ else
++ widget.secondary_icon_name = 'gtk-dialog-warning'
++ widget.secondary_icon_tooltip_text =
++ _('Value must be an integer greater than 0')
++ end
++
++ update_values
++ end
++
++ def self.convert_fixed_select_toggled(widget, path)
++ iter = @fixeds.get_iter(path)
++ iter[CONVERT_FIXED_CONVERT] = !iter[CONVERT_FIXED_CONVERT]
++ end
++
++ def self.convert_removable_select_toggled(widget, path)
++ iter = @removables.get_iter(path)
++ iter[CONVERT_REMOVABLE_CONVERT] = !iter[CONVERT_REMOVABLE_CONVERT]
++ end
++
++ def self.convert_network_select_toggled(widget, path)
++ iter = @nics.get_iter(path)
++ iter[CONVERT_NETWORK_CONVERT] = !iter[CONVERT_NETWORK_CONVERT]
++ end
++
++ def self.convert_button_clicked
++ event(EV_BUTTON, true)
++ end
++
++end # module
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/main.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/main.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/main.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/main.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,110 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'gtk2'
++require 'virt-p2v/gtk-queue'
++
++module VirtP2V
++module UI
++
++class Main
++ def get_object(name)
++ o = @builder.get_object(name)
++ raise "Object #{name} not found in ui" unless o != nil
++
++ return o
++ end
++
++ def show
++ @builder.connect_signals { |signal|
++ raise "No hander for signal #{signal}" \
++ unless @signal_handlers.has_key?(signal)
++
++ @signal_handlers[signal]
++ }
++
++ # Display the main window
++ main = self.get_object('main_window')
++ main.show_all()
++ end
++
++ def register_handler(signal, handler)
++ @signal_handlers[signal] = handler
++ end
++
++ def main_loop
++ Gtk.main_with_queue 100
++ end
++
++ def active_page=(name)
++ raise "Attempt to activate non-existent page #{name}" \
++ unless @pages.has_key?(name)
++
++ page = @pages[name]
++
++ @page_vbox = self.get_object('page_vbox') unless defined? @page_vbox
++ @page_vbox.remove(@selected) if defined? @selected
++ @page_vbox.add(page)
++ @selected = page
++ end
++
++ def active_page
++ return @selected
++ end
++
++ def quit
++ Gtk.main_quit()
++ end
++
++ private
++
++ def initialize
++ @builder = Gtk::Builder.new()
++
++ # Find the UI definition in $LOAD_PATH
++ i = $LOAD_PATH.index { |path|
++ File.exists?(path + '/virt-p2v/ui/p2v.ui')
++ }
++ @builder.add_from_file($LOAD_PATH[i] + '/virt-p2v/ui/p2v.ui')
++
++ @signal_handlers = {}
++ self.register_handler('gtk_main_quit', method(:quit))
++
++ # Configure the Wizard page frame
++ # Can't change these colours from glade for some reason
++ self.get_object('title_background').
++ modify_bg(Gtk::STATE_NORMAL, Gdk::Color.parse('#86ABD9'))
++ self.get_object('page_frame').
++ modify_fg(Gtk::STATE_NORMAL, Gdk::Color.parse('#86ABD9'))
++
++ # Load all pages from glade
++ @pages = {}
++ [ 'network_win', 'server_win',
++ 'conversion_win', 'success_win' ].each { |name|
++ page = self.get_object(name)
++
++ child = page.children[0]
++ page.remove(child)
++ @pages[name] = child
++ }
++
++ # Set a default first page
++ self.active_page = 'network_win'
++ end
++end
++
++end # UI
++end # VirtP2V
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/network.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/network.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/network.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/network.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,317 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'gettext'
++require 'gtk2'
++require 'ipaddr'
++require 'virt-p2v/netdevice'
++
++module VirtP2V::UI::Network
++ include GetText
++
++ # The indices of Device List colums, taken from glade
++ DEVCOL_NAME = 0
++ DEVCOL_MAC = 1
++ DEVCOL_STATUS = 2
++ DEVCOL_AVAILABLE = 3
++
++ UI_STATE_INVALID = 0
++ UI_STATE_VALID = 1
++ UI_STATE_ACTIVATING = 2
++ UI_STATE_COMPLETE = 3
++
++ EV_IP_CONFIG = 0
++ EV_SELECTION = 1
++ EV_BUTTON = 2
++ EV_ACTIVATION = 3
++
++ def self.event(event, status)
++ case event
++ when EV_IP_CONFIG
++ @ip_config = status
++ when EV_SELECTION
++ @selected = status
++ when EV_BUTTON, EV_ACTIVATION
++ # Persistent state not required
++ else
++ raise "Unexpected NetworkConfig event: #{event}"
++ end
++
++ case @state
++ when UI_STATE_INVALID
++ if @ip_config && @selected then
++ set_state(UI_STATE_VALID)
++ end
++ when UI_STATE_VALID
++ if !@ip_config || !@selected then
++ set_state(UI_STATE_INVALID)
++ elsif event == EV_BUTTON
++ set_state(UI_STATE_ACTIVATING)
++ end
++ when UI_STATE_ACTIVATING
++ # UI is disabled and we're waiting for EV_ACTIVATION, but we could
++ # also get events triggered by NetworkManager signals.
++
++ if event == EV_ACTIVATION then
++ if status then
++ set_state(UI_STATE_COMPLETE)
++ else
++ set_state(UI_STATE_VALID)
++ end
++ elsif !@ip_config || !@selected then
++ set_state(UI_STATE_INVALID)
++ end
++ else
++ raise "Unexpected NetworkConfig UI state: #{@state}"
++ end
++ end
++
++ def self.init(ui)
++ # Configure initial defaults
++ @manual_mode = false
++ @ip_address = nil
++ @ip_prefix = nil
++ @ip_gateway = nil
++ @ip_dns = nil
++ @state = UI_STATE_INVALID
++ @ip_config = false
++ @selected = false
++
++ @network_button = ui.get_object('network_button')
++ @device_list_frame = ui.get_object('device_list_frame')
++ @ipv4_config_frame = ui.get_object('ipv4_config_frame')
++ @dl_selection = ui.get_object('network_device_list_view').
++ selection
++ @device_list = ui.get_object('network_device_list')
++ @manual_ui = ui.get_object('ip_manual')
++ @ip_address_ui = ui.get_object('ip_address')
++ @ip_prefix_ui = ui.get_object('ip_prefix')
++ @ip_gateway_ui = ui.get_object('ip_gateway')
++ @ip_dns_ui = ui.get_object('ip_dns')
++
++ ui.register_handler('network_button_clicked',
++ method(:network_button_clicked))
++ ui.register_handler('ip_auto_toggled',
++ method(:ip_auto_toggled))
++ ui.register_handler('ip_address_changed',
++ method(:ip_address_changed))
++ ui.register_handler('ip_prefix_changed',
++ method(:ip_prefix_changed))
++ ui.register_handler('ip_gateway_changed',
++ method(:ip_gateway_changed))
++ ui.register_handler('ip_dns_changed',
++ method(:ip_dns_changed))
++
++ check_config_valid()
++
++ # The user may only select a single device
++ @dl_selection.mode = Gtk::SELECTION_SINGLE
++
++ @dl_selection.set_select_function { |selection, model, path, current|
++ iter = model.get_iter(path)
++
++ # This is a toggle event. The new state is the opposite of the
++ # current state
++ new_state = !current
++
++ # Don't allow the user to select an unavailable device
++ if new_state then
++ # Notify the config UI if we're selecting a device
++ if iter[DEVCOL_AVAILABLE] then
++ event(EV_SELECTION, true)
++ end
++
++ iter[DEVCOL_AVAILABLE]
++
++ # Always allow the user to unselect a device
++ else
++ # Notify the UI that we're unselecting the device
++ event(EV_SELECTION, false)
++ true
++ end
++ }
++
++ # Store a map of device names to row references
++ refs = {}
++
++ # Populate the device list with all detected network devices
++ VirtP2V::NetworkDevice.all_devices.each { |device|
++ iter = @device_list.append()
++
++ iter[DEVCOL_NAME] = device.name
++ iter[DEVCOL_MAC] = device.mac
++ iter[DEVCOL_STATUS] = device.state
++ iter[DEVCOL_AVAILABLE] = device.connected
++
++ # Store a stable reference to this row in the TreeModel
++ refs[device.name] =
++ Gtk::TreeRowReference.new(@device_list, iter.path)
++ }
++
++ # Listen for updates to device states
++ VirtP2V::NetworkDevice.add_listener( lambda { |device|
++ path = refs[device.name].path
++
++ iter = @device_list.get_iter(path)
++ iter[DEVCOL_STATUS] = device.state
++ iter[DEVCOL_AVAILABLE] = device.connected
++
++ # Notify the UI that a device was activated
++ event(EV_ACTIVATION, device.activated) \
++ unless device.activated.nil?
++
++ # Unselect the path if it was previously selected and is no
++ # longer available
++ if !device.connected && @dl_selection.iter_is_selected?(iter)
++ then
++ @dl_selection.unselect_all()
++ event(EV_SELECTION, false)
++ end
++ } )
++
++ @ui = ui
++ end
++
++ def self.set_state(state)
++ # Don't do anything if state hasn't changed
++ return if state == @state
++
++ case state
++ when UI_STATE_INVALID
++ @network_button.sensitive = false
++ @device_list_frame.sensitive = true
++ @ipv4_config_frame.sensitive = true
++
++ @state = UI_STATE_INVALID
++ when UI_STATE_VALID
++ @network_button.sensitive = true
++ @device_list_frame.sensitive = true
++ @ipv4_config_frame.sensitive = true
++
++ @state = UI_STATE_VALID
++ when UI_STATE_ACTIVATING
++ @network_button.sensitive = false
++ @device_list_frame.sensitive = false
++ @ipv4_config_frame.sensitive = false
++
++ @state = UI_STATE_ACTIVATING
++ when UI_STATE_COMPLETE
++ # Activate the next page
++ @ui.active_page = 'server_win'
++
++ # ... then leave this one as we hope to find it if we come back here
++ set_state(UI_STATE_VALID)
++ else
++ raise "Attempt to set unexected NetworkConfig UI state: #{@state}"
++ end
++ end
++
++ def self.network_button_clicked
++ event(EV_BUTTON, true)
++
++ iter = @dl_selection.selected
++ return if iter.nil? # Shouldn't be possible
++ name = iter[DEVCOL_NAME]
++
++ VirtP2V::NetworkDevice[name].activate(!@manual_mode, @ip_address,
++ @ip_prefix, @ip_gateway, @ip_dns)
++ end
++
++ def self.ip_auto_toggled
++ @manual_mode = !@manual_mode
++ @manual_ui.sensitive = @manual_mode
++
++ check_config_valid()
++ end
++
++ def self.ip_address_changed
++ @ip_address = parse_ip(@ip_address_ui)
++
++ check_config_valid()
++ end
++
++ # Check IP prefix is a positive integer
++ # We check that it's appropriate to the address class in use elsewhere
++ def self.ip_prefix_changed
++ begin
++ @ip_prefix = Integer(@ip_prefix_ui.text)
++ rescue ArgumentError => e
++ # Ignore the result if it didn't parse
++ @ip_prefix = nil
++ return
++ end
++
++ if @ip_prefix < 0 then
++ @ip_prefix = nil
++ end
++
++ check_config_valid()
++ end
++
++ def self.ip_gateway_changed
++ @ip_gateway = parse_ip(@ip_gateway_ui)
++
++ check_config_valid()
++ end
++
++ # Parse an IP address understood by IPAddr
++ def self.parse_ip(entry)
++ a = entry.text.strip
++
++ begin
++ ip = IPAddr.new(a)
++ rescue ArgumentError => e
++ # Ignore the result if it didn't parse
++ ip = nil
++ end
++
++ return ip
++ end
++
++ def self.ip_dns_changed
++ dns = @ip_dns_ui.text
++
++ @ip_dns = []
++ dns.split(/\s*,+\s*/).each { |entry|
++ begin
++ @ip_dns << IPAddr.new(entry)
++ rescue ArgumentError => e
++ @ip_dns = ()
++ break
++ end
++ }
++ end
++
++ def self.check_config_valid
++ if !@manual_mode || (!@ip_address.nil? &&
++ !@ip_prefix.nil? &&
++ !@ip_gateway.nil?) then
++ if @manual_mode then
++ # Check that IPv4/IPv6 is used consistently
++ if @ip_address.ipv4? then
++ event(EV_IP_CONFIG, @ip_gateway.ipv4? && @ip_prefix < 32)
++ else
++ event(EV_IP_CONFIG, @ip_gateway.ipv6? && @ip_prefix < 128)
++ end
++ else
++ event(EV_IP_CONFIG, true)
++ end
++ else
++ event(EV_IP_CONFIG, false)
++ end
++ end
++
++end # module
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/p2v.ui virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/p2v.ui
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/p2v.ui 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/p2v.ui 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,1031 @@
++<?xml version="1.0"?>
++<interface>
++ <requires lib="gtk+" version="2.16"/>
++ <!-- interface-naming-policy project-wide -->
++ <object class="GtkWindow" id="main_window">
++ <property name="resizable">False</property>
++ <property name="window_position">center-always</property>
++ <property name="decorated">False</property>
++ <signal name="destroy" handler="gtk_main_quit"/>
++ <child>
++ <object class="GtkAlignment" id="alignment2">
++ <property name="visible">True</property>
++ <property name="xscale">0</property>
++ <property name="yscale">0</property>
++ <child>
++ <object class="GtkFrame" id="page_frame">
++ <property name="width_request">800</property>
++ <property name="height_request">600</property>
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="label_yalign">0</property>
++ <property name="shadow_type">in</property>
++ <child>
++ <object class="GtkVBox" id="page_vbox">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <property name="spacing">2</property>
++ <child>
++ <object class="GtkEventBox" id="title_background">
++ <property name="visible">True</property>
++ <child>
++ <object class="GtkLabel" id="title_label">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">5</property>
++ <property name="ypad">5</property>
++ <property name="label"><span weight='bold' foreground='white' size='xx-large'>virt-p2v</span></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <placeholder/>
++ </child>
++ </object>
++ </child>
++ <child type="label_item">
++ <placeholder/>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ <object class="GtkListStore" id="network_device_list">
++ <columns>
++ <!-- column-name Name -->
++ <column type="gchararray"/>
++ <!-- column-name MAC -->
++ <column type="gchararray"/>
++ <!-- column-name Status -->
++ <column type="gchararray"/>
++ <!-- column-name Available -->
++ <column type="gboolean"/>
++ </columns>
++ </object>
++ <object class="GtkListStore" id="convert_network_list">
++ <columns>
++ <!-- column-name Convert -->
++ <column type="gboolean"/>
++ <!-- column-name Device -->
++ <column type="gchararray"/>
++ </columns>
++ <signal name="row_changed" handler="convert_network_list_row_changed"/>
++ </object>
++ <object class="GtkListStore" id="convert_fixed_list">
++ <columns>
++ <!-- column-name Convert -->
++ <column type="gboolean"/>
++ <!-- column-name Device -->
++ <column type="gchararray"/>
++ <!-- column-name Progress -->
++ <column type="gdouble"/>
++ </columns>
++ <signal name="row_changed" handler="convert_fixed_list_row_changed"/>
++ </object>
++ <object class="GtkListStore" id="convert_removable_list">
++ <columns>
++ <!-- column-name Convert -->
++ <column type="gboolean"/>
++ <!-- column-name Device -->
++ <column type="gchararray"/>
++ <!-- column-name Type -->
++ <column type="gchararray"/>
++ </columns>
++ <signal name="row_changed" handler="convert_removable_list_row_changed"/>
++ </object>
++ <object class="GtkListStore" id="convert_profile_list">
++ <columns>
++ <!-- column-name Name -->
++ <column type="gchararray"/>
++ </columns>
++ </object>
++ <object class="GtkWindow" id="network_win">
++ <property name="width_request">800</property>
++ <property name="height_request">550</property>
++ <child>
++ <object class="GtkVBox" id="vbox1">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <child>
++ <object class="GtkLabel" id="label1">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="yalign">1</property>
++ <property name="ypad">11</property>
++ <property name="label" translatable="yes">Welcome to virt-p2v.</property>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkFrame" id="device_list_frame">
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">out</property>
++ <child>
++ <object class="GtkScrolledWindow" id="scrolledwindow1">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="hscrollbar_policy">automatic</property>
++ <property name="vscrollbar_policy">automatic</property>
++ <child>
++ <object class="GtkTreeView" id="network_device_list_view">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="model">network_device_list</property>
++ <property name="headers_clickable">False</property>
++ <property name="search_column">0</property>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
++ <property name="title">Device</property>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext1"/>
++ <attributes>
++ <attribute name="sensitive">3</attribute>
++ <attribute name="text">0</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
++ <property name="fixed_width">18</property>
++ <property name="title">MAC Address</property>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext3"/>
++ <attributes>
++ <attribute name="sensitive">3</attribute>
++ <attribute name="text">1</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
++ <property name="title">Status</property>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext2"/>
++ <attributes>
++ <attribute name="sensitive">3</attribute>
++ <attribute name="text">2</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label5">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"><b>Select a network device</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkFrame" id="ipv4_config_frame">
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">in</property>
++ <child>
++ <object class="GtkAlignment" id="alignment1">
++ <property name="visible">True</property>
++ <property name="left_padding">12</property>
++ <child>
++ <object class="GtkVBox" id="vbox2">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <child>
++ <object class="GtkCheckButton" id="ip_auto">
++ <property name="label" translatable="yes">Automatic configuration</property>
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="receives_default">False</property>
++ <property name="active">True</property>
++ <property name="draw_indicator">True</property>
++ <signal name="toggled" handler="ip_auto_toggled"/>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkTable" id="ip_manual">
++ <property name="visible">True</property>
++ <property name="sensitive">False</property>
++ <property name="n_rows">3</property>
++ <property name="n_columns">2</property>
++ <property name="column_spacing">2</property>
++ <child>
++ <object class="GtkLabel" id="label3">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">IP Address:</property>
++ </object>
++ <packing>
++ <property name="x_options">GTK_FILL</property>
++ <property name="y_options">GTK_FILL</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label8">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Gateway:</property>
++ </object>
++ <packing>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ <property name="x_options">GTK_FILL</property>
++ <property name="y_options">GTK_FILL</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label4">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">DNS Servers:</property>
++ </object>
++ <packing>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ <property name="x_options">GTK_FILL</property>
++ <property name="y_options">GTK_FILL</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="ip_gateway">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="max_length">39</property>
++ <property name="width_chars">39</property>
++ <property name="truncate_multiline">True</property>
++ <signal name="changed" handler="ip_gateway_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ <property name="y_options">GTK_FILL</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="ip_dns">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="width_chars">35</property>
++ <signal name="changed" handler="ip_dns_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ <property name="y_options">GTK_FILL</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkHBox" id="hbox6">
++ <property name="visible">True</property>
++ <property name="spacing">2</property>
++ <child>
++ <object class="GtkEntry" id="ip_address">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="max_length">39</property>
++ <property name="width_chars">39</property>
++ <property name="truncate_multiline">True</property>
++ <signal name="changed" handler="ip_address_changed"/>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label7">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Prefix:</property>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="ip_prefix">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="max_length">2</property>
++ <property name="width_chars">2</property>
++ <property name="truncate_multiline">True</property>
++ <signal name="changed" handler="ip_prefix_changed"/>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">2</property>
++ </packing>
++ </child>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="y_options">GTK_FILL</property>
++ </packing>
++ </child>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label2">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"><b>IP Configuration</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">2</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkAlignment" id="alignment3">
++ <property name="visible">True</property>
++ <property name="xalign">1</property>
++ <property name="xscale">0</property>
++ <child>
++ <object class="GtkButton" id="network_button">
++ <property name="label" translatable="yes">Use these network settings</property>
++ <property name="visible">True</property>
++ <property name="sensitive">False</property>
++ <property name="can_focus">True</property>
++ <property name="receives_default">True</property>
++ <signal name="clicked" handler="network_button_clicked"/>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">3</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ </object>
++ <object class="GtkWindow" id="server_win">
++ <child>
++ <object class="GtkVBox" id="vbox3">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <child>
++ <object class="GtkAlignment" id="alignment4">
++ <property name="visible">True</property>
++ <property name="xscale">0</property>
++ <property name="yscale">0</property>
++ <child>
++ <object class="GtkFrame" id="connect_frame">
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">in</property>
++ <child>
++ <object class="GtkAlignment" id="alignment9">
++ <property name="visible">True</property>
++ <property name="left_padding">12</property>
++ <child>
++ <object class="GtkVBox" id="vbox5">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <child>
++ <object class="GtkTable" id="table1">
++ <property name="visible">True</property>
++ <property name="n_rows">3</property>
++ <property name="n_columns">2</property>
++ <property name="column_spacing">2</property>
++ <child>
++ <object class="GtkLabel" id="label9">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Hostname:</property>
++ </object>
++ <packing>
++ <property name="x_options"></property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label10">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Username:</property>
++ </object>
++ <packing>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ <property name="x_options"></property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label11">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Password:</property>
++ </object>
++ <packing>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ <property name="x_options"></property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="server_hostname">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="invisible_char">•</property>
++ <property name="width_chars">40</property>
++ <signal name="changed" handler="server_hostname_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="server_password">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="visibility">False</property>
++ <property name="invisible_char">•</property>
++ <property name="width_chars">40</property>
++ <signal name="changed" handler="server_password_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="server_username">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="invisible_char">•</property>
++ <property name="width_chars">40</property>
++ <property name="text" translatable="yes">root</property>
++ <signal name="changed" handler="server_username_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="connect_error">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">8</property>
++ <property name="ypad">8</property>
++ <attributes>
++ <attribute name="foreground" value="#ffff00000000"/>
++ </attributes>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label6">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"><b>Connect to conversion server</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkAlignment" id="alignment5">
++ <property name="visible">True</property>
++ <property name="xalign">1</property>
++ <property name="yalign">0</property>
++ <property name="xscale">0</property>
++ <property name="yscale">0</property>
++ <child>
++ <object class="GtkButton" id="connect_button">
++ <property name="label" translatable="yes">Connect</property>
++ <property name="visible">True</property>
++ <property name="sensitive">False</property>
++ <property name="can_focus">True</property>
++ <property name="receives_default">True</property>
++ <signal name="clicked" handler="connect_button_clicked"/>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ </object>
++ <object class="GtkWindow" id="conversion_win">
++ <child>
++ <object class="GtkVBox" id="vbox4">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <child>
++ <object class="GtkHBox" id="convert_editable">
++ <property name="visible">True</property>
++ <child>
++ <object class="GtkFrame" id="frame2">
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">out</property>
++ <child>
++ <object class="GtkAlignment" id="alignment6">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xscale">0</property>
++ <property name="yscale">0</property>
++ <property name="left_padding">12</property>
++ <child>
++ <object class="GtkTable" id="table2">
++ <property name="visible">True</property>
++ <property name="n_rows">4</property>
++ <property name="n_columns">2</property>
++ <property name="column_spacing">2</property>
++ <child>
++ <object class="GtkLabel" id="label14">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Destination Profile:</property>
++ </object>
++ </child>
++ <child>
++ <object class="GtkComboBox" id="convert_profile">
++ <property name="visible">True</property>
++ <property name="model">convert_profile_list</property>
++ <signal name="changed" handler="convert_profile_changed"/>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext8"/>
++ <attributes>
++ <attribute name="text">0</attribute>
++ </attributes>
++ </child>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label16">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Memory (MB):</property>
++ </object>
++ <packing>
++ <property name="top_attach">3</property>
++ <property name="bottom_attach">4</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="convert_memory">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="invisible_char">•</property>
++ <property name="truncate_multiline">True</property>
++ <signal name="changed" handler="convert_memory_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">3</property>
++ <property name="bottom_attach">4</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label15">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Number of CPUs:</property>
++ </object>
++ <packing>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkLabel" id="label18">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="label" translatable="yes">Name</property>
++ </object>
++ <packing>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="convert_name">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="invisible_char">•</property>
++ <property name="truncate_multiline">True</property>
++ <signal name="changed" handler="convert_name_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkEntry" id="convert_cpus">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="invisible_char">•</property>
++ <property name="truncate_multiline">True</property>
++ <signal name="changed" handler="convert_cpus_changed"/>
++ </object>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label13">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"><b>Target properties</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkVBox" id="vbox6">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <child>
++ <object class="GtkFrame" id="frame3">
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">out</property>
++ <child>
++ <object class="GtkAlignment" id="alignment8">
++ <property name="visible">True</property>
++ <child>
++ <object class="GtkScrolledWindow" id="scrolledwindow2">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="hscrollbar_policy">automatic</property>
++ <property name="vscrollbar_policy">automatic</property>
++ <child>
++ <object class="GtkTreeView" id="treeview1">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="model">convert_fixed_list</property>
++ <property name="headers_clickable">False</property>
++ <property name="search_column">0</property>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn4">
++ <property name="title">Convert</property>
++ <property name="clickable">True</property>
++ <child>
++ <object class="GtkCellRendererToggle" id="convert_fixed_select">
++ <signal name="toggled" handler="convert_fixed_select_toggled"/>
++ </object>
++ <attributes>
++ <attribute name="active">0</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn5">
++ <property name="title">Device</property>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext4"/>
++ <attributes>
++ <attribute name="text">1</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn8">
++ <property name="title">Transfer Progress</property>
++ <property name="expand">True</property>
++ <child>
++ <object class="GtkCellRendererProgress" id="cellrendererprogress1"/>
++ <attributes>
++ <attribute name="value">2</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label17">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"><b>Fixed Storage</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkFrame" id="frame4">
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">out</property>
++ <child>
++ <object class="GtkAlignment" id="alignment11">
++ <property name="visible">True</property>
++ <child>
++ <object class="GtkScrolledWindow" id="scrolledwindow4">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="hscrollbar_policy">automatic</property>
++ <property name="vscrollbar_policy">automatic</property>
++ <child>
++ <object class="GtkTreeView" id="treeview3">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="model">convert_removable_list</property>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn9">
++ <property name="title">Convert</property>
++ <child>
++ <object class="GtkCellRendererToggle" id="convert_removable_select">
++ <signal name="toggled" handler="convert_removable_select_toggled"/>
++ </object>
++ <attributes>
++ <attribute name="active">0</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn10">
++ <property name="title">Device</property>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext6"/>
++ <attributes>
++ <attribute name="text">1</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn11">
++ <property name="title">Type</property>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext7"/>
++ <attributes>
++ <attribute name="text">2</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label19">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"><b>Removable Media</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkFrame" id="frame1">
++ <property name="visible">True</property>
++ <property name="label_xalign">0</property>
++ <property name="shadow_type">out</property>
++ <child>
++ <object class="GtkAlignment" id="alignment10">
++ <property name="visible">True</property>
++ <property name="xalign">1</property>
++ <property name="yalign">1</property>
++ <child>
++ <object class="GtkScrolledWindow" id="scrolledwindow3">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="hscrollbar_policy">automatic</property>
++ <property name="vscrollbar_policy">automatic</property>
++ <child>
++ <object class="GtkTreeView" id="treeview2">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="model">convert_network_list</property>
++ <property name="headers_clickable">False</property>
++ <property name="search_column">0</property>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn6">
++ <property name="title">Convert</property>
++ <child>
++ <object class="GtkCellRendererToggle" id="convert_network_select">
++ <signal name="toggled" handler="convert_network_select_toggled"/>
++ </object>
++ <attributes>
++ <attribute name="active">0</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ <child>
++ <object class="GtkTreeViewColumn" id="treeviewcolumn7">
++ <property name="title">Device</property>
++ <child>
++ <object class="GtkCellRendererText" id="cellrenderertext5"/>
++ <attributes>
++ <attribute name="text">1</attribute>
++ </attributes>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ </object>
++ </child>
++ <child type="label">
++ <object class="GtkLabel" id="label12">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"><b>Network Interfaces</b></property>
++ <property name="use_markup">True</property>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="position">2</property>
++ </packing>
++ </child>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkHBox" id="hbox1">
++ <property name="visible">True</property>
++ <child>
++ <object class="GtkLabel" id="convert_status">
++ <property name="visible">True</property>
++ <property name="xalign">0</property>
++ <property name="xpad">12</property>
++ <attributes>
++ <attribute name="foreground" value="#ffff00000000"/>
++ </attributes>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkButton" id="convert_button">
++ <property name="label" translatable="yes">Convert</property>
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="receives_default">True</property>
++ <signal name="clicked" handler="convert_button_clicked"/>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ </object>
++ <packing>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ </object>
++ <object class="GtkWindow" id="success_win">
++ <child>
++ <object class="GtkVBox" id="vbox7">
++ <property name="visible">True</property>
++ <property name="orientation">vertical</property>
++ <child>
++ <object class="GtkLabel" id="label20">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">A guest has been successfully created on the target server.
++
++Remove the temporary boot device from this machine and press 'Reboot' to continue.</property>
++ <property name="justify">center</property>
++ </object>
++ <packing>
++ <property name="position">0</property>
++ </packing>
++ </child>
++ <child>
++ <object class="GtkAlignment" id="alignment7">
++ <property name="visible">True</property>
++ <property name="xscale">0.25</property>
++ <property name="yscale">0.25</property>
++ <child>
++ <object class="GtkButton" id="reboot_button">
++ <property name="label" translatable="yes">Reboot</property>
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="receives_default">True</property>
++ <signal name="clicked" handler="reboot_button_clicked"/>
++ </object>
++ </child>
++ </object>
++ <packing>
++ <property name="position">1</property>
++ </packing>
++ </child>
++ </object>
++ </child>
++ </object>
++</interface>
+diff -ruN virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/success.rb virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/success.rb
+--- virt-v2v-v0.8.1/p2v/client/lib/virt-p2v/ui/success.rb 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/lib/virt-p2v/ui/success.rb 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,33 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'gettext'
++
++module VirtP2V::UI::Success
++ include GetText
++
++ def self.init(ui)
++ ui.register_handler('reboot_button_clicked',
++ method(:reboot_button_clicked))
++
++ @ui = ui
++ end
++
++ def self.reboot_button_clicked
++ @ui.quit
++ end
++
++end # module
+diff -ruN virt-v2v-v0.8.1/p2v/client/Manifest virt-v2v-v0.8.1.new/p2v/client/Manifest
+--- virt-v2v-v0.8.1/p2v/client/Manifest 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/Manifest 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,15 @@
++Rakefile
++bin/virt-p2v
++lib/virt-p2v/blockdevice.rb
++lib/virt-p2v/connection.rb
++lib/virt-p2v/converter.rb
++lib/virt-p2v/gtk-queue.rb
++lib/virt-p2v/netdevice.rb
++lib/virt-p2v/ui/connect.rb
++lib/virt-p2v/ui/convert.rb
++lib/virt-p2v/ui/main.rb
++lib/virt-p2v/ui/network.rb
++lib/virt-p2v/ui/p2v.ui
++lib/virt-p2v/ui/success.rb
++virt-p2v.gemspec
++Manifest
+diff -ruN virt-v2v-v0.8.1/p2v/client/Rakefile virt-v2v-v0.8.1.new/p2v/client/Rakefile
+--- virt-v2v-v0.8.1/p2v/client/Rakefile 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/client/Rakefile 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,37 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++require 'rubygems'
++require 'echoe'
++
++Echoe.new("virt-p2v") do |p|
++ p.project = "Virt P2V"
++ p.version = `../../Build version`
++ p.author = "Matthew Booth"
++ p.summary = "Send a machine's storage and metadata to virt-p2v-server"
++ p.description = <<EOF
++virt-p2v is a client which connects to a virt-p2v-server and transfer's the host
++machine's storage and metadata. virt-p2v is intended to be run from a live
++image, so it is unlikely you want to install it.
++EOF
++ p.url = "http://libguestfs.org"
++ p.email = "libguestfs at redhat.com"
++ p.runtime_dependencies = [
++ 'gtk2',
++ 'gettext',
++ 'net-ssh'
++ ]
++end
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/common-install.ks virt-v2v-v0.8.1.new/p2v/image-builder/common-install.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/common-install.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/common-install.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,54 @@
++lang C
++keyboard us
++timezone --utc UTC
++auth --useshadow --enablemd5
++selinux --disabled
++firewall --disabled
++# TODO: the sizing of the image needs to be more dynamic
++part / --size 1024 --fstype ext2
++services --enabled=NetworkManager --disabled=auditd
++bootloader --timeout=30
++rootpw --iscrypted $1$tQiZwocX$ghhurQEm56p/HqgN.XEtk1
++
++# add missing scsi modules to initramfs
++device 3w-9xxx
++device 3w-sas
++device 3w-xxxx
++device a100u2w
++device aacraid
++device aic79xx
++device aic94xx
++device arcmsr
++device atp870u
++device be2iscsi
++device bfa
++device BusLogic
++device cxgb3i
++device dc395x
++device fnic
++device gdth
++device hpsa
++device hptiop
++device imm
++device initio
++device ips
++device libosd
++device libsas
++device libsrp
++device lpfc
++device megaraid
++device megaraid_mbox
++device megaraid_mm
++device megaraid_sas
++device mpt2sas
++device mvsas
++device osd
++device osst
++device pm8001
++device pmcraid
++device qla1280
++device qla2xxx
++device qla4xxx
++device qlogicfas408
++device stex
++device tmscsim
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/common-manifest-post.ks virt-v2v-v0.8.1.new/p2v/image-builder/common-manifest-post.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/common-manifest-post.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/common-manifest-post.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,36 @@
++%post
++echo -n "Creating manifest"
++# Create post-image processing manifests
++rpm -qa --qf '%{name}-%{version}-%{release}.%{arch} (%{SIGGPG:pgpsig})\n' | \
++ sort > /manifest-rpm.txt
++rpm -qa --qf '%{sourcerpm}\n' | sort -u > /manifest-srpm.txt
++# collect all included licenses rhbz#601927
++rpm -qa --qf '%{license}\n' | sort -u > /manifest-license.txt
++# dependencies
++rpm -qa | xargs -n1 rpm -e --test 2> /manifest-deps.txt
++echo -n "."
++find / -xdev -print -exec rpm -qf {} \; > /manifest-owns.txt
++rpm -qa --qf '%{NAME}\t%{VERSION}\t%{RELEASE}\t%{BUILDTIME}\n' | \
++ sort > /rpm-qa.txt
++echo -n "."
++
++du -akx --exclude=/var/cache/yum / > /manifest-file.txt
++du -x --exclude=/var/cache/yum / > /manifest-dir.txt
++echo -n "."
++bzip2 /manifest-deps.txt /manifest-owns.txt /manifest-file.txt /manifest-dir.txt
++echo -n "."
++
++%end
++
++%post --nochroot
++# Move manifests to ISO
++mv $INSTALL_ROOT/manifest-* $LIVE_ROOT/isolinux
++echo "done"
++
++# only works on x86, x86_64
++if [ "$(uname -i)" = "i386" -o "$(uname -i)" = "x86_64" ]; then
++ if [ ! -d $LIVE_ROOT/LiveOS ]; then mkdir -p $LIVE_ROOT/LiveOS ; fi
++ cp /usr/bin/livecd-iso-to-disk $LIVE_ROOT/LiveOS
++ cp /usr/bin/livecd-iso-to-pxeboot $LIVE_ROOT/LiveOS
++fi
++%end
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/common-minimizer.ks virt-v2v-v0.8.1.new/p2v/image-builder/common-minimizer.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/common-minimizer.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/common-minimizer.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,239 @@
++# This file is only relatively lightly modified from the version copied from
++# oVirt, and certainly contains much which is irrelevant to this image. I have,
++# however, removed some obviously extraneous entries and added a few additional
++# entries.
++#
++# Matthew Booth <mbooth at redhat.com> - 18/4/2011
++
++%post --nochroot --interpreter image-minimizer
++# lokkit is just an install-time dependency; we can remove
++# it afterwards, which we do here
++droprpm system-config-*
++droprpm libsemanage-python
++droprpm python-libs
++droprpm python
++
++droprpm mkinitrd
++droprpm isomd5sum
++droprpm dmraid
++droprpm checkpolicy
++droprpm make
++droprpm policycoreutils-python
++droprpm setools-libs-python
++droprpm setools-libs
++
++droprpm gamin
++droprpm pm-utils
++droprpm kbd
++droprpm usermode
++droprpm vbetool
++droprpm ConsoleKit
++droprpm hdparm
++droprpm efibootmgr
++droprpm linux-atm-libs
++droprpm mtools
++droprpm syslinux
++droprpm wireless-tools
++droprpm radeontool
++droprpm libicu
++droprpm gnupg2
++droprpm fedora-release-notes
++droprpm fedora-logos
++
++# cronie pulls in exim (sendmail) which pulls in all kinds of perl deps
++droprpm exim
++droprpm perl*
++droprpm postfix
++droprpm mysql*
++
++droprpm sysklogd
++
++# unneeded rhn deps
++droprpm yum*
++
++# pam complains when this is missing
++keeprpm ConsoleKit-libs
++
++# kernel modules minimization
++
++# filesystems
++drop /lib/modules/*/kernel/fs
++keep /lib/modules/*/kernel/fs/ext*
++keep /lib/modules/*/kernel/fs/jbd*
++keep /lib/modules/*/kernel/fs/btrfs
++keep /lib/modules/*/kernel/fs/fat
++keep /lib/modules/*/kernel/fs/nfs
++keep /lib/modules/*/kernel/fs/nfs_common
++keep /lib/modules/*/kernel/fs/fscache
++keep /lib/modules/*/kernel/fs/lockd
++keep /lib/modules/*/kernel/fs/nls/nls_utf8.ko
++# autofs4 configfs exportfs *fat *jbd mbcache.ko nls xfs
++#*btrfs cramfs *ext2 *fscache *jbd2 *nfs squashfs
++# cachefiles dlm *ext3 fuse jffs2 *nfs_common ubifs
++# cifs ecryptfs *ext4 gfs2 *lockd nfsd udf
++
++# network
++drop /lib/modules/*/kernel/net
++keep /lib/modules/*/kernel/net/802*
++keep /lib/modules/*/kernel/net/bridge
++keep /lib/modules/*/kernel/net/core
++keep /lib/modules/*/kernel/net/ipv*
++keep /lib/modules/*/kernel/net/key
++keep /lib/modules/*/kernel/net/llc
++keep /lib/modules/*/kernel/net/netfilter
++keep /lib/modules/*/kernel/net/rds
++keep /lib/modules/*/kernel/net/sctp
++keep /lib/modules/*/kernel/net/sunrpc
++#*802 atm can ieee802154 *key *netfilter rfkill *sunrpc xfrm
++#*8021q bluetooth *core *ipv4 *llc phonet sched wimax
++# 9p *bridge dccp *ipv6 mac80211 *rds *sctp wireless
++
++drop /lib/modules/*/kernel/sound
++
++# drivers
++drop /lib/modules/*/kernel/drivers
++keep /lib/modules/*/kernel/drivers/ata
++keep /lib/modules/*/kernel/drivers/block
++keep /lib/modules/*/kernel/drivers/cdrom
++keep /lib/modules/*/kernel/drivers/char
++keep /lib/modules/*/kernel/drivers/cpufreq
++keep /lib/modules/*/kernel/drivers/dca
++keep /lib/modules/*/kernel/drivers/dma
++keep /lib/modules/*/kernel/drivers/edac
++keep /lib/modules/*/kernel/drivers/firmware
++keep /lib/modules/*/kernel/drivers/idle
++keep /lib/modules/*/kernel/drivers/infiniband
++keep /lib/modules/*/kernel/drivers/md
++keep /lib/modules/*/kernel/drivers/message
++keep /lib/modules/*/kernel/drivers/net
++drop /lib/modules/*/kernel/drivers/net/pcmcia
++drop /lib/modules/*/kernel/drivers/net/wireless
++drop /lib/modules/*/kernel/drivers/net/ppp*
++keep /lib/modules/*/kernel/drivers/pci
++keep /lib/modules/*/kernel/drivers/scsi
++keep /lib/modules/*/kernel/drivers/staging/ramzswap
++keep /lib/modules/*/kernel/drivers/uio
++keep /lib/modules/*/kernel/drivers/usb
++drop /lib/modules/*/kernel/drivers/usb/atm
++drop /lib/modules/*/kernel/drivers/usb/class
++drop /lib/modules/*/kernel/drivers/usb/image
++drop /lib/modules/*/kernel/drivers/usb/misc
++drop /lib/modules/*/kernel/drivers/usb/serial
++keep /lib/modules/*/kernel/drivers/vhost
++keep /lib/modules/*/kernel/drivers/virtio
++
++# acpi *cpufreq hid leds mtd ?regulator uwb
++#*ata crypto ?hwmon *md *net* rtc *vhost
++# atm *dca ?i2c media ?parport *scsi* video
++# auxdisplay *dma *idle memstick *pci ?serial *virtio
++#*block *edac ieee802154 *message pcmcia ?ssb watchdog
++# bluetooth firewire *infiniband ?mfd platform *staging xen
++#*cdrom *firmware input misc ?power ?uio
++#*char* ?gpu isdn mmc ?pps *usb
++
++drop /usr/share/zoneinfo
++keep /usr/share/zoneinfo/UTC
++
++drop /etc/alsa
++drop /usr/share/alsa
++drop /usr/share/awk
++drop /usr/share/vim
++drop /usr/share/anaconda
++drop /usr/share/backgrounds
++drop /usr/share/wallpapers
++drop /usr/share/kde-settings
++drop /usr/share/gnome-background-properties
++drop /usr/share/dracut
++drop /usr/share/plymouth
++drop /usr/share/setuptool
++drop /usr/share/hwdata/MonitorsDB
++drop /usr/share/hwdata/oui.txt
++drop /usr/share/hwdata/videoaliases
++drop /usr/share/hwdata/videodrivers
++drop /usr/share/firstboot
++drop /usr/share/lua
++drop /usr/share/kde4
++drop /usr/share/pixmaps
++drop /usr/share/icons
++drop /usr/share/fedora-release
++drop /usr/share/tabset
++
++drop /usr/share/tc
++drop /usr/share/emacs
++drop /usr/share/info
++drop /usr/src
++drop /usr/etc
++drop /usr/games
++drop /usr/include
++drop /usr/local
++drop /usr/sbin/dell*
++keep /usr/sbin/build-locale-archive
++drop /usr/sbin/glibc_post_upgrade.*
++drop /usr/lib*/tc
++drop /usr/lib*/tls
++drop /usr/lib*/sse2
++drop /usr/lib*/pkgconfig
++drop /usr/lib*/nss
++drop /usr/lib*/games
++drop /usr/lib*/alsa-lib
++drop /usr/lib*/krb5
++drop /usr/lib*/hal
++drop /usr/lib*/gio
++
++# syslinux
++drop /usr/share/syslinux
++# glibc-common locales
++drop /usr/lib/locale
++keep /usr/lib/locale/usr/share/locale/en_US
++# openssh
++drop /usr/bin/sftp
++drop /usr/bin/slogin
++drop /usr/bin/ssh-add
++drop /usr/bin/ssh-agent
++drop /usr/bin/ssh-keyscan
++# docs
++drop /usr/share/omf
++drop /usr/share/gnome
++drop /usr/share/doc
++keep /usr/share/doc/*-firmware-*
++drop /usr/share/locale/
++keep /usr/share/locale/en_US
++drop /usr/share/man
++drop /usr/share/i18n
++drop /boot/*
++drop /var/lib/builder
++
++drop /usr/lib*/libboost*
++keep /usr/lib*/libboost_program_options.so*
++keep /usr/lib*/libboost_filesystem.so*
++keep /usr/lib*/libboost_thread-mt.so*
++keep /usr/lib*/libboost_system.so*
++drop /usr/kerberos
++keep /usr/kerberos/bin/kinit
++keep /usr/kerberos/bin/klist
++drop /lib/firmware
++keep /lib/firmware/3com
++keep /lib/firmware/acenic
++keep /lib/firmware/adaptec
++keep /lib/firmware/advansys
++keep /lib/firmware/bnx2
++keep /lib/firmware/cxgb3
++keep /lib/firmware/e100
++keep /lib/firmware/myricom
++keep /lib/firmware/ql*
++keep /lib/firmware/sun
++keep /lib/firmware/tehuti
++keep /lib/firmware/tigon
++drop /lib/kbd/consolefonts
++drop /etc/pki/tls
++drop /etc/pki/java
++drop /etc/pki/nssdb
++drop /etc/pki/rpm-gpg
++%end
++
++%post
++echo "Removing python source files"
++find / -name '*.py' -exec rm -f {} \;
++find / -name '*.pyo' -exec rm -f {} \;
++
++%end
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/common-pkgs.ks virt-v2v-v0.8.1.new/p2v/image-builder/common-pkgs.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/common-pkgs.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/common-pkgs.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,48 @@
++# Direct requirements
++rubygem-virt-p2v
++bitstream-vera-sans-fonts
++xorg-x11-xinit
++xorg-x11-drivers
++xorg-x11-server-Xorg
++
++# Boot requirements
++device-mapper
++
++# Required for livecd creation
++passwd
++rpm
++/usr/sbin/lokkit
++
++# Remove unnecessary packages
++-audit-libs-python
++-ustr
++-authconfig
++-wireless-tools
++-setserial
++-prelink
++-newt-python
++-newt
++-libselinux-python
++-kbd
++-usermode
++-fedora-release
++-fedora-release-notes
++-dmraid
++-gzip
++-less
++-which
++-parted
++-tar
++-libuser
++-mtools
++-cpio
++-yum
++-numactl # Pulls in perl dependency
++-perl
++
++# qlogic firmware
++ql2100-firmware
++ql2200-firmware
++ql23xx-firmware
++ql2400-firmware
++ql2500-firmware
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/common-post.ks virt-v2v-v0.8.1.new/p2v/image-builder/common-post.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/common-post.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/common-post.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,43 @@
++# -*-Shell-script-*-
++echo "Starting Kickstart Post"
++PATH=/sbin:/usr/sbin:/bin:/usr/bin
++export PATH
++
++# cleanup rpmdb to allow non-matching host and chroot RPM versions
++rm -f /var/lib/rpm/__db*
++
++echo "Creating shadow files"
++# because we aren't installing authconfig, we aren't setting up shadow
++# and gshadow properly. Do it by hand here
++pwconv
++grpconv
++
++echo "Forcing C locale"
++# force logins (via ssh, etc) to use C locale, since we remove locales
++cat >> /etc/profile << \EOF
++# force our locale to C since we don't have locale stuff'
++export LC_ALL=C LANG=C
++EOF
++
++# remove errors from /sbin/dhclient-script
++DHSCRIPT=/sbin/dhclient-script
++sed -i 's/mv /cp -p /g' $DHSCRIPT
++sed -i '/rm -f.*${interface}/d' $DHSCRIPT
++sed -i '/rm -f \/etc\/localtime/d' $DHSCRIPT
++sed -i '/rm -f \/etc\/ntp.conf/d' $DHSCRIPT
++sed -i '/rm -f \/etc\/yp.conf/d' $DHSCRIPT
++
++# Lock root account
++#passwd -l root
++
++#strip out all unncesssary locales
++localedef --list-archive | grep -v -i -E 'en_US.utf8' |xargs localedef --delete-from-archive
++mv /usr/lib/locale/locale-archive /usr/lib/locale/locale-archive.tmpl
++/usr/sbin/build-locale-archive
++
++# Run virt-p2v
++cat >> /etc/rc.local <<EOF
++export HOME=/root # rubygem Net::SSH needs this
++/usr/bin/xinit /usr/bin/virt-p2v > /root/virt-p2v.log 2>&1
++poweroff
++EOF
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/common-post-nochroot.ks virt-v2v-v0.8.1.new/p2v/image-builder/common-post-nochroot.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/common-post-nochroot.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/common-post-nochroot.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,60 @@
++%include version.ks
++
++PRODUCT='Virt P2V'
++PRODUCT_SHORT='virt-p2v'
++PACKAGE='virt-p2v'
++RELEASE=${RELEASE:-devel.`date +%Y%m%d%H%M%S`}
++
++echo "Customizing boot menu"
++sed -i -e '
++# Put product information at the top of the file
++1 {
++ i '"say $PRODUCT $VERSION ($RELEASE)"'
++ i '"menu title $PRODUCT_SHORT $VERSION ($RELEASE)"'
++}
++
++# Remove any existing menu title
++/^menu title .*/d
++
++# Remove quiet bootparam
++#s/ quiet//
++
++# Disable selinux entirely. Required, as we dont install an SELinux policy.
++/^\s*append\s/ s/\s*$/ selinux=0/
++
++# Remove Verify and Boot option
++/label check0/{N;N;N;d;}
++
++# Set the default timeout to 15 seconds
++s/^timeout .*/timeout 15/
++' $LIVE_ROOT/isolinux/isolinux.cfg
++
++# TODO: Replace the splash screen with something P2V appropriate
++#cp $INSTALL_ROOT//syslinux-vesa-splash.jpg $LIVE_ROOT/isolinux/splash.jpg
++
++# store image version info in the ISO
++cat > $LIVE_ROOT/isolinux/version <<EOF
++PRODUCT='$PRODUCT'
++PRODUCT_SHORT='${PRODUCT_SHORT}'
++PRODUCT_CODE=$PRODUCT_CODE
++RECIPE_SHA256=$RECIPE_SHA256
++RECIPE_RPM=$RECIPE_RPM
++PACKAGE=$PACKAGE
++VERSION=$VERSION
++RELEASE=$RELEASE
++EOF
++
++# overwrite user visible banners with the image versioning info
++cat > $INSTALL_ROOT/etc/$PACKAGE-release <<EOF
++$PRODUCT release $VERSION ($RELEASE)
++EOF
++ln -snf $PACKAGE-release $INSTALL_ROOT/etc/redhat-release
++ln -snf $PACKAGE-release $INSTALL_ROOT/etc/system-release
++cp $INSTALL_ROOT/etc/$PACKAGE-release $INSTALL_ROOT/etc/issue
++echo "Kernel \r on an \m (\l)" >> $INSTALL_ROOT/etc/issue
++cp $INSTALL_ROOT/etc/issue $INSTALL_ROOT/etc/issue.net
++
++# replace initramfs if regenerated
++if [ -f "$INSTALL_ROOT/initrd0.img" ]; then
++ mv -v "$INSTALL_ROOT/initrd0.img" "$LIVE_ROOT/isolinux/initrd0.img"
++fi
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/Makefile virt-v2v-v0.8.1.new/p2v/image-builder/Makefile
+--- virt-v2v-v0.8.1/p2v/image-builder/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/Makefile 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,2 @@
++version.ks: ../../Build
++ echo VERSION=`../../Build version` > version.ks
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/version.ks virt-v2v-v0.8.1.new/p2v/image-builder/version.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/version.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/version.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1 @@
++VERSION=0.8.1
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/virt-p2v-image-builder virt-v2v-v0.8.1.new/p2v/image-builder/virt-p2v-image-builder
+--- virt-v2v-v0.8.1/p2v/image-builder/virt-p2v-image-builder 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/virt-p2v-image-builder 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,188 @@
++#!/bin/bash
++
++# Copyright (C) 2010-2011, Red Hat, Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; version 2 of the License.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++# MA 02110-1301, USA. A copy of the GNU General Public License is
++# also available at http://www.gnu.org/copyleft/gpl.html.
++
++# Requires: sudo livecd-creator, sudo setenforce, ksflatten
++
++# Based on oVirt's node-creator
++
++# Current fedora data
++cur_rawhide=16
++cur_devel=15
++
++me=$(basename "$0")
++warn() { printf '%s: %s\n' "$me" "$*" >&2; }
++die() { warn "$*"; exit 1; }
++usage() {
++cat <<EOF
++usage: $me <options>
++
++Build a virt-p2v bootable image.
++
++OPTIONS:
++ -a Additional yum repository. Can be specified multiple times.
++ -c Yum cache directory.
++ -d Directory containing virt-p2v-image.ks.
++ -f Specific Fedora mirror to use if building a Fedora image.
++ -l Boot image label.
++ -r Primary yum repository.
++ -u Updates yum repository.
++ -h Show this message.
++EOF
++}
++
++onlyonce() {
++ warn "-$1 may only be specified once"
++ usage
++ exit 1
++}
++
++while getopts "a:d:f:hl:r:u:w:" OPTION
++do
++ case $OPTION in
++ a)
++ n_elems=${#extra_repos[*]}
++ extra_repos[$n_elems]="$OPTARG"
++ ;;
++ c)
++ [ -n "$cachedir" ] && onlyonce $OPTION
++ cachedir="$OPTARG"
++ ;;
++ d)
++ [ -n "$datadir" ] && onlyonce $OPTION
++ datadir="$OPTARG"
++ ;;
++ f)
++ [ -n "$fedora_url" ] && onlyonce $OPTION
++ fedora_url="$OPTARG"
++ ;;
++ l)
++ [ -n "$label" ] && onlyonce $OPTION
++ label="$OPTARG"
++ ;;
++ r)
++ [ -n "$repo" ] && onlyonce $OPTION
++ repo="$OPTARG"
++ ;;
++ u)
++ [ -n "$updates" ] && onlyonce $OPTION
++ updates="$OPTARG"
++ ;;
++ h)
++ usage
++ exit 0
++ ;;
++ ?)
++ usage
++ exit 1
++ ;;
++ esac
++done
++
++# Split out here for simple editing with sed during installation
++DEFAULT_DATADIR=.
++
++# Option defaults
++datadir="${datadir:-$DEFAULT_DATADIR}"
++cachedir="${cachedir:-/var/tmp/p2v-image-builder.$USER}"
++label="${label:-Virt-P2V}"
++
++arch=$(rpm --eval '%{_arch}')
++kstmp=$(mktemp --tmpdir p2v-image-builder.XXXXXXXX)
++
++if pgrep -xl nscd; then
++ die "Please stop nscd first"
++fi
++
++rm -f "$kstmp"
++# combine recipe includes
++ksflatten --config "$datadir/virt-p2v-image.ks" --output "$kstmp"
++# XXX broken ksflatten leaves %include
++sed -i 's/^%include /#&/' "$kstmp"
++
++if [ -z "$repo" ]; then
++ # Set defaults for Fedora if this is a fedora system
++ fedora=$(rpm --eval '%{fedora}' |grep [0-9])
++
++ mirrorlist="http://mirrors.fedoraproject.org/mirrorlist"
++
++ case "$fedora" in
++ $curr_rawhide)
++ if [ -z "$fedora_url" ]; then
++ repo="--mirrorlist=$mirrorlist?repo=rawhide&arch=$arch"
++ else
++ repo="--baseurl=$fedora_url/development/rawhide/$arch/os"
++ fi
++ ;;
++ $cur_devel)
++ if [ -z "$fedora_url" ]; then
++ repo="--mirrorlist=$mirrorlist?repo=fedora-$fedora&arch=$arch"
++ else
++ repo="--baseurl=$fedora_url/development/$fedora/$arch/os"
++ fi
++ ;;
++ ?*)
++ if [ -z "$fedora_url" ]; then
++ repo="--mirrorlist=$mirrorlist?repo=fedora-$fedora&arch=$arch"
++ updates="--mirrorlist=$mirrorlist?repo=updates-released-f${fedora}&arch=$arch"
++ else
++ repo="--baseurl=$fedora_url/releases/$fedora/Everything/$arch/os"
++ updates="--baseurl=$fedora_url/updates/$fedora/$arch"
++ fi
++ esac
++else
++ repo="--baseurl=$repo"
++ [ -n "$updates" ] && updates="--baseurl=$updates"
++fi
++
++if [ -n "$repo" ]; then
++ echo "repo --name=base $repo" >> "$kstmp"
++else
++ die "No repository specified, and no default available."
++fi
++if [ -n "$updates" ]; then
++ echo "repo --name=updates $updates" >> "$kstmp"
++fi
++i=0
++for extra in "${extra_repos[@]}"; do
++ ((i++))
++ [ -d "$extra" ] && extra="file://$extra"
++ echo "repo --name=extra$i --baseurl=$extra" >> "$kstmp"
++done
++
++selinux_enforcing=$(/usr/sbin/getenforce)
++case "$selinux_enforcing" in
++ Enforcing) sudo /usr/sbin/setenforce Permissive ;;
++ Permissive) ;;
++ *) if grep -q '^selinux --disabled' "$kstmp";
++ then
++ warn "WARNING: SELinux disabled in kickstart"
++ else
++ die "ERROR: SELinux enabled in kickstart, \
++ but disabled on the build machine"
++ fi ;;
++esac
++
++mkdir -p $cachedir
++sudo livecd-creator -c "$kstmp" -f "$label" --cache="$cachedir"
++
++# Clean up
++rm -f $kstmp
++if [ "$selinux_enforcing" = Enforcing ]; then
++ sudo /usr/sbin/setenforce Enforcing
++fi
+diff -ruN virt-v2v-v0.8.1/p2v/image-builder/virt-p2v-image.ks virt-v2v-v0.8.1.new/p2v/image-builder/virt-p2v-image.ks
+--- virt-v2v-v0.8.1/p2v/image-builder/virt-p2v-image.ks 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/image-builder/virt-p2v-image.ks 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,19 @@
++# virt-p2v Node image recipe
++
++%include common-install.ks
++
++%packages --excludedocs --nobase
++%include common-pkgs.ks
++%end
++
++%post
++%include common-post.ks
++%end
++
++%include common-minimizer.ks
++
++%post --nochroot
++%include common-post-nochroot.ks
++%end
++
++%include common-manifest-post.ks
+diff -ruN virt-v2v-v0.8.1/p2v/server/run-p2v-locally virt-v2v-v0.8.1.new/p2v/server/run-p2v-locally
+--- virt-v2v-v0.8.1/p2v/server/run-p2v-locally 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/server/run-p2v-locally 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,52 @@
++#!/bin/sh
++# virt-p2v
++# Copyright (C) 2010 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++# This script sets up the environment so you can run virt-v2v in place
++# without needing to do 'make install' first.
++#
++# Use it like this:
++# ./run-p2v-locally
++#
++# It requires the environment variable VIRTV2V_ROOT to be set. If using
++# libguestfs from source, LIBGUESTFS_ROOT must also be set.
++
++if [ -z "$VIRTV2V_ROOT" ]; then
++ echo "VIRTV2V_ROOT must be set"
++ exit 1
++fi
++
++if [ -z "$PERL5LIB" ]; then
++ PERL5LIB="$VIRTV2V_ROOT/blib/lib"
++else
++ PERL5LIB="$VIRTV2V_ROOT/blib/lib:$PERL5LIB"
++fi
++
++if [ ! -z "$LIBGUESTFS_ROOT" ]; then
++ if [ -z "$LD_LIBRARY_PATH" ]; then
++ LD_LIBRARY_PATH="$LIBGUESTFS_ROOT/src/.libs"
++ else
++ LD_LIBRARY_PATH="$LIBGUESTFS_ROOT/src/.libs:$LD_LIBRARY_PATH"
++ fi
++
++ LIBGUESTFS_PATH="$LIBGUESTFS_ROOT/appliance"
++ PERL5LIB="$LIBGUESTFS_ROOT/perl/blib/lib:$LIBGUESTFS_ROOT/perl/blib/arch:$PERL5LIB"
++fi
++
++export PERL5LIB LD_LIBRARY_PATH LIBGUESTFS_PATH
++
++exec perl "$VIRTV2V_ROOT/p2v-server/virt-p2v-server.pl" "$@"
+diff -ruN virt-v2v-v0.8.1/p2v/server/virt-p2v-server.pl virt-v2v-v0.8.1.new/p2v/server/virt-p2v-server.pl
+--- virt-v2v-v0.8.1/p2v/server/virt-p2v-server.pl 1970-01-01 01:00:00.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v/server/virt-p2v-server.pl 2011-05-11 17:20:21.000000000 +0100
+@@ -0,0 +1,505 @@
++#!/usr/bin/perl
++# virt-p2v-server
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++use warnings;
++use strict;
++
++use IO::Handle;
++use YAML::Any;
++
++use Locale::TextDomain 'virt-v2v';
++
++use Sys::Guestfs;
++
++use Sys::VirtConvert;
++use Sys::VirtConvert::Config;
++use Sys::VirtConvert::Converter;
++use Sys::VirtConvert::Connection::LibVirtTarget;
++use Sys::VirtConvert::Connection::RHEVTarget;
++use Sys::VirtConvert::GuestfsHandle;
++use Sys::VirtConvert::Util qw(:DEFAULT logmsg_init logmsg_level);
++
++=encoding utf8
++
++=head1 NAME
++
++virt-p2v-server - Receive data from virt-p2v
++
++=head1 DESCRIPTION
++
++virt-p2v-server is invoked over SSH by virt-p2v. It is not intended to be run
++manually.
++
++=cut
++
++# SIGPIPE will cause an untidy exit of the perl process, without calling
++# destructors. We don't rely on it anywhere, as we check for errors when reading
++# from or writing to a pipe.
++$SIG{'PIPE'} = 'IGNORE';
++
++# The protocol version we support
++use constant VERSION => 0;
++
++# Message types
++use constant MSG_VERSION => 'VERSION';
++use constant MSG_LANG => 'LANG';
++use constant MSG_METADATA => 'METADATA';
++use constant MSG_PATH => 'PATH';
++use constant MSG_CONVERT => 'CONVERT';
++use constant MSG_LIST_PROFILES => 'LIST_PROFILES';
++use constant MSG_SET_PROFILE => 'SET_PROFILE';
++use constant MSG_CONTAINER => 'CONTAINER';
++use constant MSG_DATA => 'DATA';
++
++# Container types
++use constant CONT_RAW => 'RAW';
++
++# Global state
++my $config;
++my $meta;
++my $target;
++
++# Initialize logging
++logmsg_init('syslog');
++#logmsg_level(DEBUG);
++
++logmsg NOTICE, __x("{program} started.", program => 'p2v-server');
++
++# Wrap everything in a big eval to catch any die(). N.B. $SIG{__DIE__} is no
++# good for this, as it catches every die(), even those inside an eval
++eval {
++ # Set the umask to a reasonable default
++ umask(0022);
++
++ # Don't buffer output
++ # While perl will use line buffering when STDOUT is connected to a tty, when
++ # not connected to a tty, for example when invoked directly over ssh, it
++ # will use a regular, large output buffer. This results in messages being
++ # held in the buffer indefinitely.
++ STDOUT->autoflush(1);
++
++ # Read the config file
++ eval {
++ $config = Sys::VirtConvert::Config->new('/etc/virt-v2v.conf');
++ };
++ v2vdie $@ if $@;
++
++ my $msg;
++ while ($msg = p2v_receive()) {
++ my $type = $msg->{type};
++
++ # VERSION n
++ if ($type eq MSG_VERSION) {
++ my $version = $msg->{args}[0];
++ if ($version <= VERSION) {
++ p2v_return_ok();
++ }
++
++ else {
++ err_and_die(__x('This version of virt-p2v-server does not '.
++ 'support protocol version {version}.',
++ version => $version));
++ }
++ }
++
++ # LANG lang
++ elsif ($type eq MSG_LANG) {
++ $ENV{LANG} = $msg->{args}[0];
++ p2v_return_ok();
++ }
++
++ # METADATA length
++ # length bytes of YAML
++ elsif ($type eq MSG_METADATA) {
++ my $yaml = p2v_read($msg->{args}[0]);
++ eval { $meta = Load($yaml); };
++ err_and_die('Error parsing metadata: '.$@) if $@;
++
++ p2v_return_ok();
++ }
++
++ # PATH length path
++ # N.B. path could theoretically include spaces
++ elsif ($type eq MSG_PATH) {
++ my $length = $msg->{args}[0];
++
++ my $path = join(' ', @{$msg->{args}}[1..$#{$msg->{args}}]);
++ receive_path($path, $length);
++ }
++
++ # CONVERT
++ elsif ($type eq MSG_CONVERT) {
++ convert();
++ }
++
++ # LIST_PROFILES
++ elsif ($type eq MSG_LIST_PROFILES) {
++ p2v_return_list($config->list_profiles());
++ }
++
++ # SET_PROFILE profile
++ elsif ($type eq MSG_SET_PROFILE) {
++ set_profile($msg->{args}[0]);
++ }
++
++ else {
++ unexpected_msg($type);
++ }
++ }
++};
++logmsg FATAL, $@ if $@;
++
++exit(0);
++
++# Receive an image file
++sub receive_path
++{
++ my ($path, $length) = @_;
++
++ err_and_die('PATH without prior SET_PROFILE command')
++ unless defined($target);
++ err_and_die('PATH without prior METADATA command')
++ unless defined($meta);
++
++ my ($disk) = grep { $_->{path} eq $path } @{$meta->{disks}};
++ err_and_die("$path not found in metadata") unless defined($disk);
++
++ # Construct a volume name based on the path and hostname
++ my $name = $meta->{name}.'-'.$disk->{device};
++ $name =~ s,/,_,g; # e.g. cciss devices have a directory structure
++
++ my $sopts = $config->get_storage_opts();
++
++ my $convert = 0;
++ my $format;
++ my $sparse;
++
++ # Default to raw. Conversion required for anything else.
++ if (!exists($sopts->{format}) || $sopts->{format} eq 'raw') {
++ $format = 'raw';
++ } else {
++ $format = $sopts->{format};
++ $convert = 1;
++ }
++
++ # Default to non-sparse
++ my $allocation = $sopts->{allocation};
++ if (!defined($allocation) || $allocation eq 'preallocated') {
++ $sparse = 0;
++ } elsif ($allocation eq 'sparse') {
++ $sparse = 1;
++ } else {
++ err_and_die(__x('Invalid allocation policy {policy} in profile.',
++ policy => $allocation));
++ }
++
++ # Create the target volume
++ my $vol;
++ eval {
++ $vol = $target->create_volume(
++ $name,
++ $format,
++ $length,
++ $sparse
++ );
++ };
++ err_and_die($@) if $@;
++ p2v_return_ok();
++
++ # Receive an initial container
++ my $msg = p2v_receive();
++ unexpected_msg($msg->{type}) unless $msg->{type} eq MSG_CONTAINER;
++
++ # We only support RAW container
++ my $ctype = $msg->{args}[0];
++ err_and_die("Received unknown container type: $ctype")
++ unless $ctype eq CONT_RAW;
++ p2v_return_ok();
++
++ # Update the disk entry with the new volume details
++ $disk->{local_path} = $vol->get_local_path();
++ $disk->{path} = $vol->get_path();
++ $disk->{is_block} = $vol->is_block();
++
++ my $writer = $vol->get_write_stream($convert);
++
++ # Receive volume data in chunks
++ my $received = 0;
++ while ($received < $length) {
++ my $data = p2v_receive();
++
++ unexpected_msg($data->command) unless $data->{type} eq MSG_DATA;
++
++ # Read the data message in chunks of up to 4M
++ my $remaining = $data->{args}[0];
++ while ($remaining > 0) {
++ my $chunk = $remaining > 4*1024*1024 ? 4*1024*1024 : $remaining;
++ my $buf = p2v_read($chunk);
++
++ $received += $chunk;
++ $remaining -= $chunk;
++
++ eval { $writer->write($buf); };
++ err_and_die($@) if $@;
++ }
++
++ p2v_return_ok();
++ }
++}
++
++# Use the specified profile
++sub set_profile
++{
++ my ($profile) = @_;
++
++ # Check the profile is in our list
++ my $found = 0;
++ for my $i ($config->list_profiles()) {
++ if ($i eq $profile) {
++ $found = 1;
++ last;
++ }
++ }
++ err_and_die(__x('Invalid profile: {profile}', profile => $profile))
++ unless ($found);
++
++ $config->use_profile($profile);
++
++ my $storage = $config->get_storage();
++ my $method = $config->get_method();
++ if ($method eq 'libvirt') {
++ $target = new Sys::VirtConvert::Connection::LibVirtTarget
++ ('qemu:///system', $storage);
++ } elsif ($method eq 'rhev') {
++ $target = new Sys::VirtConvert::Connection::RHEVTarget($storage);
++ } else {
++ err_and_die(__x('Profile {profile} specifies invalid method {method}.',
++ profile => $profile, method => $method));
++ }
++
++ p2v_return_ok();
++}
++
++sub convert
++{
++ err_and_die('CONVERT without prior SET_PROFILE command')
++ unless (defined($target));
++
++ err_and_die('CONVERT without prior METADATA command')
++ unless defined($meta);
++
++ my @localpaths = map { $_->{local_path} } @{$meta->{disks}};
++
++ my $g;
++ eval {
++ my $transferiso = $config->get_transfer_iso();
++
++ $g = new Sys::VirtConvert::GuestfsHandle(
++ \@localpaths,
++ $transferiso,
++ $target->isa('Sys::VirtConvert::Connection::RHEVTarget')
++ );
++
++ my $transferdev;
++ if (defined($transferiso)) {
++ my @devices = $g->list_devices();
++ $transferdev = pop(@devices);
++ }
++
++ my $root = inspect_guest($g, $transferdev);
++ my $guestcaps =
++ Sys::VirtConvert::Converter->convert($g, $config, $root, $meta);
++ $target->create_guest($g, $root, $meta, $config, $guestcaps,
++ $meta->{name});
++
++ if($guestcaps->{block} eq 'virtio' && $guestcaps->{net} eq 'virtio') {
++ logmsg NOTICE, __x('{name} configured with virtio drivers.',
++ name => $meta->{name});
++ } elsif ($guestcaps->{block} eq 'virtio') {
++ logmsg NOTICE, __x('{name} configured with virtio storage only.',
++ name => $meta->{name});
++ } elsif ($guestcaps->{net} eq 'virtio') {
++ logmsg NOTICE, __x('{name} configured with virtio networking only.',
++ name => $meta->{name});
++ } else {
++ logmsg NOTICE, __x('{name} configured without virtio drivers.',
++ name => $meta->{name});
++ }
++ };
++
++ # If any of the above commands result in failure, we need to ensure that
++ # the guestfs qemu process is cleaned up before further cleanup. Failure to
++ # do this can result in failure to umount RHEV export's temporary mount
++ # point.
++ if ($@) {
++ my $err = $@;
++ $g->close();
++
++ # We trust the error was already logged
++ p2v_return_err($err);
++ die($@);
++ }
++
++ p2v_return_ok();
++}
++
++sub unexpected_msg
++{
++ err_and_die('Received unexpected command: '.shift);
++}
++
++sub err_and_die
++{
++ my $err = shift;
++ p2v_return_err($err);
++ v2vdie $err;
++}
++
++END {
++ my $err = $?;
++
++ logmsg NOTICE, __x("{program} exited.", program => 'p2v-server');
++
++ # die() sets $? to 255, which is untidy.
++ $? = $err == 255 ? 1 : $err;
++}
++
++# Perform guest inspection using the libguestfs core inspection API.
++# Returns the root device of the os to be converted.
++sub inspect_guest
++{
++ my $g = shift;
++ my $transferdev = shift;
++
++ # Get list of roots, sorted
++ my @roots = $g->inspect_os();
++
++ # Filter out the transfer device from the results of inspect_os
++ # There's a libguestfs bug (fixed upstream) which meant the transfer ISO
++ # could be erroneously detected as an unknown Windows OS. As we know what it
++ # is, we can filter out the transfer device here. Even when the fix is
++ # released this is reasonable belt & braces.
++ @roots = grep(!/^\Q$transferdev\E$/, @roots);
++
++ @roots = sort @roots;
++
++ # Only work on single-root operating systems.
++ v2vdie __('No root device found in this operating system image.')
++ if @roots == 0;
++
++ v2vdie __('Multiboot operating systems are not supported.')
++ if @roots > 1;
++
++ return $roots[0];
++}
++
++sub p2v_receive
++{
++ my $in = <>;
++ v2vdie __('Client closed connection unexpectedly') unless defined($in);
++
++ # Messages consist of the message type followed by 0 or more arguments,
++ # terminated by a newline
++ chomp($in);
++ $in =~ /^([A-Z_]+)( .+)?$/ or err_and_die("Received invalid message: $in");
++
++ my %msg;
++ $msg{type} = $1;
++ if (defined($2)) {
++ my @args = split(' ', $2);
++ $msg{args} = \@args;
++ } else {
++ $msg{args} = [];
++ }
++
++ logmsg DEBUG, __x('Received: {command} {args}',
++ command => $msg{type},
++ args => join(' ', @{$msg{args}}));
++
++ return \%msg;
++}
++
++sub p2v_read
++{
++ my ($length) = @_;
++
++ my $buf;
++ my $total = 0;
++
++ while($total < $length) {
++ my $in = read(STDIN, $buf, $length, $total)
++ or err_and_die(__x('Error receiving data: {error}', error => $@));
++ logmsg DEBUG, "Read $in bytes";
++ $total += $in;
++ }
++
++ return $buf;
++}
++
++sub p2v_return_ok
++{
++ my $msg = "OK";
++ logmsg DEBUG, __x('Sent: {msg}', msg => $msg);
++ print $msg,"\n";
++}
++
++sub p2v_return_list
++{
++ my @values = @_;
++
++ my $msg = 'LIST '.scalar(@values);
++ foreach my $value (@values) {
++ $msg .= "\n$value";
++ }
++ logmsg DEBUG, __x('Sent: {msg}', msg => $msg);
++ print $msg,"\n";
++}
++
++sub p2v_return_err
++{
++ my $msg = 'ERROR '.shift;
++ logmsg DEBUG, __x('Sent: {msg}', msg => $msg);
++ print $msg,"\n";
++}
++
++=head1 SEE ALSO
++
++L<virt-v2v(1)>,
++L<http://libguestfs.org/>.
++
++=head1 AUTHOR
++
++Matthew Booth <mbooth at redhat.com>
++
++=head1 COPYRIGHT
++
++Copyright (C) 2011 Red Hat Inc.
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2 of the License, or
++(at your option) any later version.
++
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+diff -ruN virt-v2v-v0.8.1/p2v-client/bin/virt-p2v virt-v2v-v0.8.1.new/p2v-client/bin/virt-p2v
+--- virt-v2v-v0.8.1/p2v-client/bin/virt-p2v 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/bin/virt-p2v 1970-01-01 01:00:00.000000000 +0100
+@@ -1,62 +0,0 @@
+-#!/usr/bin/env ruby
+-
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'virt-p2v/ui/main'
+-require 'virt-p2v/ui/network'
+-require 'virt-p2v/ui/connect'
+-require 'virt-p2v/ui/convert'
+-require 'virt-p2v/ui/success'
+-
+-require 'virt-p2v/converter'
+-require 'virt-p2v/netdevice'
+-
+-require 'gettext'
+-
+-include GetText
+-
+-bindtextdomain('virt-p2v')
+-
+-if Process.uid != 0
+- puts _("virt-p2v must be executed with root privileges.\n" +
+- "It is intended to be included in a custom Live image, not " +
+- "run from the command\nline.")
+- abort
+-end
+-
+-converter = VirtP2V::Converter.new
+-
+-# Initialise the wizard UI
+-ui = VirtP2V::UI::Main.new
+-
+-# Initialize wizard pages
+-VirtP2V::UI::Network.init(ui)
+-VirtP2V::UI::Connect.init(ui, converter)
+-VirtP2V::UI::Convert.init(ui, converter)
+-VirtP2V::UI::Success.init(ui)
+-
+-# Skip the network configuration screen if there is already an active network
+-# connection
+-VirtP2V::NetworkDevice.all_devices.each { |device|
+- if device.activated then
+- ui.active_page = 'server_win'
+- break
+- end
+-}
+-
+-ui.show
+-ui.main_loop
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/blockdevice.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/blockdevice.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/blockdevice.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/blockdevice.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,112 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-module VirtP2V
+-
+-class NoSuchDeviceError < StandardError; end
+-
+-class FixedBlockDevice
+- @@devices = {}
+-
+- def self.all_devices
+- @@devices.values
+- end
+-
+- def self.[](device)
+- raise NoSuchDeviceError unless @@devices.has_key?(device)
+-
+- @@devices[device]
+- end
+-
+- attr_reader :device
+-
+- def initialize(device)
+- @device = device
+- @@devices[device] = self
+- end
+-end
+-
+-class RemovableBlockDevice
+- @@devices = {}
+-
+- def self.all_devices
+- @@devices.values
+- end
+-
+- def self.[](device)
+- raise NoSuchDeviceError unless @@devices.has_key?(device)
+-
+- @@devices[device]
+- end
+-
+- attr_reader :device, :type
+-
+- def initialize(device, type)
+- @device = device
+- @type = type
+-
+- @@devices[device] = self
+- end
+-end
+-
+-# Detect and instantiate all fixed and removable block devices in the system
+-begin
+- # Look for block devices
+- # Specifically, we look for entries in /sys/block which have a device
+- # symlink and no entries in their slaves subdirectory
+- Dir.foreach('/sys/block') { |dev|
+- next if dev == '.' || dev == '..'
+-
+- # Skip if there's no device link
+- next unless File.exists?("/sys/block/#{dev}/device")
+-
+- # Skip if the slaves subdirectory contains anything other than . and
+- # ..
+- begin
+- next if Dir.entries("/sys/block/#{dev}/slaves").length > 2
+- rescue Errno::ENOENT => ex
+- # This shouldn't happen, but if it did I guess it would mean
+- # there are no slave devices
+- end
+-
+- # We've got a real block device. Check if it's removable or not
+- File.open("/sys/block/#{dev}/removable") { |fd|
+- removable = fd.gets.chomp
+- if removable == "0" then
+- FixedBlockDevice.new(dev)
+- else
+- # Look in device/modalias to work out what kind of removable
+- # device this is
+- type = File.open(
+- "/sys/block/#{dev}/device/modalias") \
+- { |modalias_f|
+- modalias = modalias_f.gets.chomp
+- if modalias =~ /floppy/ then
+- 'floppy'
+- elsif modalias =~ /cdrom/ then
+- 'cdrom'
+- else
+- # We don't know what this is, ignore it
+- end
+- }
+-
+- RemovableBlockDevice.new(dev, type) unless type.nil?
+- end
+- }
+- }
+-end
+-
+-end
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/connection.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/connection.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/connection.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/connection.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,320 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'gettext'
+-require 'rubygems'
+-require 'net/ssh'
+-require 'thread'
+-require 'yaml'
+-
+-require 'virt-p2v/gtk-queue'
+-
+-module VirtP2V
+-
+-class Connection
+- include GetText
+-
+- attr_reader :connected
+-
+- class InvalidHostnameError < StandardError; end
+- class InvalidCredentialsError < StandardError; end
+- class TransportError < StandardError; end
+- class NoP2VError < StandardError; end
+- class RemoteError < StandardError; end
+- class ProtocolError < StandardError; end
+- class NotConnectedError < StandardError; end
+-
+- def on_connect(&cb)
+- @connection_listeners << cb
+- end
+-
+- def initialize(hostname, username, password, &cb)
+- @mutex = Mutex.new
+- @connection_listeners = []
+-
+- # Always send our version number on connection
+- @connection_listeners << Proc.new { |cb|
+- self.version { |result| cb.call(result) }
+- }
+-
+- run(cb) {
+- error = nil
+- begin
+- @ssh = Net::SSH.start(hostname, username, :password => password)
+- rescue SocketError, Errno::EHOSTUNREACH => ex
+- raise InvalidHostnameError
+- raise ex
+- rescue Net::SSH::AuthenticationFailed => ex
+- raise InvalidCredentialsError
+- raise ex
+- end
+-
+- @buffer = ""
+- @connected = false
+-
+- Gtk.queue { cb.call(true) }
+- }
+- end
+-
+- def connect(&cb)
+- run(cb) {
+- @ch = @ssh.open_channel do |ch|
+- ch.exec("virt-p2v-server") do |ch, success|
+- raise RemoteError,
+- "could not execute a remote command" unless success
+-
+- ch.on_data do |ch, data|
+- @buffer << data
+- end
+-
+- # If we get anything on stderr, raise it as a RemoteError
+- ch.on_extended_data do |ch, type, data|
+- close
+- raise RemoteError, data
+- end
+-
+- # Clean up local resources if we get eof from the other end
+- ch.on_eof do |ch|
+- close
+- end
+-
+- @connected = true
+- end
+-
+- end
+-
+- # Wait until we're connected
+- @ssh.loop do
+- !@connected
+- end
+-
+- i = 0;
+- listener_result = lambda { |result|
+- if result.kind_of?(Exception)
+- cb.call(result)
+- else
+- i += 1
+- if i == @connection_listeners.length
+- cb.call(true)
+- else
+- Gtk.queue {
+- @connection_listeners[i].call(listener_result)
+- }
+- end
+- end
+- }
+- Gtk.queue { @connection_listeners[0].call(listener_result) }
+- }
+- end
+-
+- def close
+- @connected = false
+- @buffer = ""
+- @ch.close
+- end
+-
+- def version(&cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- @ch.send_data("VERSION 0\n")
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def lang(lang, &cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- @ch.send_data("LANG #{lang}\n")
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def metadata(meta, &cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- payload = YAML::dump(meta)
+- @ch.send_data("METADATA #{payload.length}\n");
+- @ch.send_data(payload)
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def path(length, path, &cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- @ch.send_data("PATH #{length} #{path}\n")
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def convert(&cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- @ch.send_data("CONVERT\n")
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def list_profiles(&cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- @ch.send_data("LIST_PROFILES\n")
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def set_profile(profile, &cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- @ch.send_data("SET_PROFILE #{profile}\n")
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def container(type, &cb)
+- raise NotConnectedError unless @connected
+-
+- run(cb) {
+- @ch.send_data("CONTAINER #{type}\n")
+- result = parse_return
+-
+- Gtk.queue { cb.call(result) }
+- }
+- end
+-
+- def send_data(io, length, progress, &completion)
+- raise NotConnectedError unless @connected
+-
+- run(completion) {
+- @ch.send_data("DATA #{length}\n")
+- total = 0
+- buffer = ''
+- begin
+- # This loop is in the habit of hanging in Net::SSH when sending
+- # a chunk larger than about 2M. Putting the 1 second wait
+- # timeout here kickstarts it if it stops.
+- @ssh.loop(1) {
+- if io.eof? || total == length then
+- false
+- else
+- if @ch.remote_window_size > 0 then
+- out = length - total
+- out = @ch.remote_window_size \
+- if out > @ch.remote_window_size
+-
+- io.read(out, buffer)
+- @ch.send_data(buffer)
+-
+- total += buffer.length
+-
+- # Send a progress callback
+- Gtk.queue { progress.call(total) }
+- end
+-
+- true
+- end
+- }
+- rescue => ex
+- Gtk.queue { completion.call(ex) }
+- end
+-
+- result = parse_return
+-
+- Gtk.queue { completion.call(result) }
+- }
+- end
+-
+- private
+-
+- def run(cb)
+- # Run the given block in a new thread
+- t = Thread.new {
+- begin
+- # We can't run more than 1 command simultaneously
+- @mutex.synchronize { yield }
+- rescue => ex
+- # Deliver exceptions to the caller, then re-raise them
+- Gtk.queue { cb.call(ex) }
+- raise ex
+- end
+- }
+- t.priority = 1
+- end
+-
+- # Return a single line of output from the remote server
+- def readline
+- # Run the event loop until the buffer contains a newline
+- index = nil
+- @ssh.loop do
+- if !@ch.eof? then
+- index = @buffer.index("\n")
+- index.nil?
+- else
+- close
+- raise RemoteError, _('Server closed connection unexpectedly')
+- end
+- end
+-
+- # Remove the line from the buffer and return it with the trailing
+- # newline removed
+- @buffer.slice!(0..index).chomp
+- end
+-
+- def parse_return
+- line = readline
+- line =~ /^(OK|ERROR|LIST)(?:\s(.*))?$/ or
+- raise ProtocolError, "Invalid server response: #{line}"
+-
+- return true if $~[1] == 'OK'
+- if $~[1] == 'ERROR' then
+- close
+- raise RemoteError, $~[2]
+- end
+-
+- # LIST response. Get the number of items, and read that many lines
+- n = Integer($~[2])
+- ret = []
+- while n > 0 do
+- n -= 1
+- ret.push(readline)
+- end
+-
+- ret
+- end
+-end
+-
+-end
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/converter.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/converter.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/converter.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/converter.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,218 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'gettext'
+-require 'rexml/document'
+-include REXML
+-
+-require 'virt-p2v/netdevice'
+-require 'virt-p2v/blockdevice'
+-
+-module VirtP2V
+-
+-# NIC
+-# hostname
+-# username
+-# password
+-
+-# 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
+-
+-class Converter
+- include GetText
+-
+- attr_accessor :profile, :name, :cpus, :memory, :arch
+- attr_reader :features, :disks, :removables, :nics
+-
+- attr_reader :connection
+-
+- def on_connection(&cb)
+- @connection_listeners << cb
+- end
+-
+- def connection=(connection)
+- @connection = connection
+- @connection_listeners.each { |cb|
+- cb.call(connection)
+- }
+- end
+-
+- 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|
+- status.call(_('Converting'))
+- @connection.convert(&cb)
+- }
+- ], completion)
+- end
+-
+- private
+-
+- def initialize()
+- @profile = nil
+- @connection = nil
+- @connection_listeners = []
+-
+- # 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 `hwloc-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 = []
+- end
+-
+- def disk(dev, status, progress, completion)
+- path = "/dev/#{dev}"
+- # XXX: No error checking of blockdev execution
+- size = Integer(`blockdev --getsize64 #{path}`.chomp)
+- 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 += 1
+- progress.call(dev, pc)
+- end
+- }, &cb)
+- }
+- ], completion)
+- end
+-
+- 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
+-
+- def meta
+- {
+- 'name' => @name,
+- 'cpus' => @cpus,
+- 'memory' => @memory,
+- 'arch' => @arch,
+- 'features' => @features,
+- 'disks' => @disks.map { |device|
+- {
+- 'device' => device,
+- 'path' => "/dev/#{device}",
+- 'is_block' => '1',
+- 'format' => 'raw'
+- }
+- },
+- '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
+-end
+-
+-end
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/gtk-queue.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/gtk-queue.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/gtk-queue.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/gtk-queue.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,52 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-# This code is taken from:
+-# http://ruby-gnome2.sourceforge.jp/hiki.cgi?tips_threads
+-# The author of the above page is given as Tal Liron
+-# The above page is distributed under the terms of the GNU FDL, although I
+-# consider this code to be too trivial to be copyrightable
+-
+-require 'gtk2'
+-require 'thread'
+-
+-module Gtk
+- GTK_PENDING_BLOCKS = []
+- GTK_PENDING_BLOCKS_LOCK = Mutex.new
+-
+- def Gtk.queue &block
+- if Thread.current == Thread.main
+- block.call
+- else
+- GTK_PENDING_BLOCKS_LOCK.synchronize do
+- GTK_PENDING_BLOCKS << block
+- end
+- end
+- end
+-
+- def Gtk.main_with_queue timeout
+- Gtk.timeout_add timeout do
+- GTK_PENDING_BLOCKS_LOCK.synchronize do
+- for block in GTK_PENDING_BLOCKS
+- block.call
+- end
+- GTK_PENDING_BLOCKS.clear
+- end
+- true
+- end
+- Gtk.main
+- end
+-end
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/netdevice.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/netdevice.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/netdevice.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/netdevice.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,259 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'dbus'
+-require 'gettext'
+-
+-module VirtP2V
+-
+-class NetworkDevice
+- include GetText
+-
+- attr_reader :name, :mac, :connected, :activated, :state
+-
+- # Some NetworkManager names, for convenience
+- CONNECTION = 'org.freedesktop.NetworkManagerSettings.Connection'.freeze
+- DEVICE = 'org.freedesktop.NetworkManager.Device'.freeze
+- NETWORKMANAGER = 'org.freedesktop.NetworkManager'.freeze
+- PROPERTIES = 'org.freedesktop.DBus.Properties'.freeze
+- SETTINGS = 'org.freedesktop.NetworkManagerSettings'.freeze
+- WIRED = 'org.freedesktop.NetworkManager.Device.Wired'.freeze
+-
+- # NetworkManager device types
+- # http://projects.gnome.org/NetworkManager/developers/spec-08.html
+- TYPE_UNKNOWN = 0
+- TYPE_ETHERNET = 1
+- TYPE_WIFI = 2
+- TYPE_GSM = 3
+- TYPE_CDMA = 4
+-
+- # NetworkManager device states
+- STATE_UNKNOWN = 0
+- STATE_UNMANAGED = 1
+- STATE_UNAVAILABLE = 2
+- STATE_DISCONNECTED = 3
+- STATE_PREPARE = 4
+- STATE_CONFIG = 5
+- STATE_NEED_AUTH = 6
+- STATE_IP_CONFIG = 7
+- STATE_ACTIVATED = 8
+- STATE_FAILED = 9
+-
+- # Human readable descriptions of NetworkManager Device States
+- STATES = {
+- 0 => _('Unknown').freeze, # For completeness
+- 1 => _('Unmanaged').freeze, # For completeness
+- 2 => _('No cable connected').freeze,
+- 3 => _('Not connected').freeze,
+- 4 => _('Preparing to connect').freeze,
+- 5 => _('Configuring').freeze,
+- 6 => _('Waiting for authentication').freeze,
+- 7 => _('Obtaining an IP address').freeze,
+- 8 => _('Connected').freeze,
+- 9 => _('Connection failed').freeze
+- }.freeze
+-
+- def initialize(obj, device, props)
+- device.default_iface = WIRED
+-
+- @nm_obj = obj
+- @name = props.Get(DEVICE, 'Interface')[0]
+- @mac = props.Get(WIRED, 'HwAddress')[0]
+- state = props.Get(WIRED, 'State')[0]
+-
+- # Lookup by name
+- @@devices[@name] = self
+-
+- state_updated(state)
+-
+- # Register a listener for state changes
+- device.on_signal('PropertiesChanged') { |props|
+- if props.has_key?('State') then
+- state_updated(props['State'])
+-
+- # Notify registered state change handlers
+- @@listeners.each { |cb| cb.call(self) }
+- end
+- }
+- end
+-
+- def self.all_devices()
+- @@devices.values
+- end
+-
+- def self.add_listener(cb)
+- @@listeners.push(cb)
+- end
+-
+- def self.[](name)
+- @@devices[name]
+- end
+-
+- def activate(auto, ip, prefix, gateway, dns)
+- # Get an IP config dependent on whether @ip_address is IPv4 or IPv6
+- ip_config = auto ? get_config_auto :
+- ip.ipv4? ? get_config_ipv4() : get_config_ipv6()
+-
+- # Create a new NetworkManager connection object
+- settings = @@nm_service.object(
+- '/org/freedesktop/NetworkManagerSettings')
+- settings.introspect()
+- settings.default_iface = SETTINGS
+-
+- uuid = `uuidgen`.chomp
+- settings.AddConnection(
+- 'connection' => {
+- 'uuid' => uuid,
+- 'id' => 'P2V',
+- 'type' => '802-3-ethernet',
+- 'autoconnect' => false
+- },
+- '802-3-ethernet' => {},
+- 'ipv4' => ip_config['ipv4'],
+- 'ipv6' => ip_config['ipv6']
+- )
+-
+- # Find the connection we just created
+- # XXX: There must be a better way to get this!
+- conn = settings.ListConnections()[0].each { |i|
+- conn = @@nm_service.object(i)
+- conn.introspect
+- conn.default_iface = CONNECTION
+-
+- break i if conn.GetSettings()[0]['connection']['uuid'] == uuid
+- }
+-
+- nm = @@nm_service.object('/org/freedesktop/NetworkManager')
+- nm.introspect
+- nm.default_iface = NETWORKMANAGER
+- nm.ActivateConnection('org.freedesktop.NetworkManagerSystemSettings',
+- conn, @nm_obj, '/')
+- end
+-
+- private
+-
+- def state_updated(state)
+- @connected = state > 2
+- @state = STATES[state]
+-
+- if state == STATE_ACTIVATED then
+- @activated = true
+- elsif state == STATE_FAILED then
+- @activated = false
+- else
+- @activated = nil
+- end
+- end
+-
+- def get_config_auto
+- {
+- 'ipv4' => {
+- 'method' => 'auto'
+- },
+- 'ipv6' => {
+- 'method' => 'ignore'
+- }
+- }
+- end
+-
+- def ipv4_to_nm(ipaddr)
+- ipaddr.hton().unpack("I")[0]
+- end
+-
+- def get_config_ipv4
+- addresses = [[ ipv4_to_nm(@ip_address), @ip_prefix,
+- ipv4_to_nm(@ip_gateway) ]]
+-
+- dns = []
+- @ip_dns.each{ |ipaddr|
+- # Only use IPv4 DNS servers
+- next unless ipaddr.ipv4?
+- dns.push(ipv4_to_nm(ipaddr))
+- }
+-
+- {
+- 'ipv4' => {
+- 'method' => 'manual',
+- 'addresses' => [ 'aau', addresses ],
+- 'dns' => [ 'au', dns ]
+- },
+- 'ipv6' => {
+- 'method' => 'ignore'
+- }
+- }
+- end
+-
+- def ipv6_to_nm(ipaddr)
+- ipaddr.hton().unpack("c*")
+- end
+-
+- def get_config_ipv6
+- dns = []
+- @ip_dns.each { |ipaddr|
+- # Only use IPv6 DNS servers
+- next unless ipaddr.ipv6?
+- dns.push(ipv6_to_nm(ipaddr))
+- }
+-
+- {
+- 'ipv4' => {
+- 'method' => 'disabled'
+- },
+- 'ipv6' => {
+- 'method' => 'manual',
+- 'addresses' => [ 'a(ayu)', [[
+- ipv6_to_nm(@ip_address),
+- @ip_prefix
+- ]] ],
+- 'routes' => [ 'a(ayuayu)', [[
+- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], 0,
+- ipv6_to_nm(@ip_gateway), 1024
+- ]] ],
+- 'dns' => [ 'aay', dns ]
+- }
+- }
+- end
+-
+- # Class initialization
+- begin
+- dbus = DBus::SystemBus.instance()
+- dbus.glibize()
+- @@nm_service = dbus.service(NETWORKMANAGER)
+-
+- nm = @@nm_service.object('/org/freedesktop/NetworkManager')
+- nm.introspect
+- nm.default_iface = NETWORKMANAGER
+-
+- @@devices = {}
+- nm.GetDevices()[0].each { |obj|
+- device = @@nm_service.object(obj)
+- device.introspect
+-
+- props = device[PROPERTIES]
+- type = props.Get(DEVICE, 'DeviceType')[0]
+-
+- # We only support ethernet devices
+- next unless type == TYPE_ETHERNET
+-
+- # Constructor will add it to @@devices
+- self.new(obj, device, props)
+- }
+-
+- @@listeners = []
+- end
+-end
+-
+-end #module
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/connect.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/connect.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/connect.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/connect.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,179 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'gettext'
+-require 'gtk2'
+-
+-require 'virt-p2v/connection'
+-
+-module VirtP2V::UI::Connect
+- include GetText
+-
+- UI_STATE_INVALID = 0
+- UI_STATE_VALID = 1
+- UI_STATE_ACTIVATING = 2
+- UI_STATE_COMPLETE = 3
+-
+- EV_HOSTNAME = 0
+- EV_USERNAME = 1
+- EV_PASSWORD = 2
+- EV_BUTTON = 3
+- EV_ACTIVATION = 4
+-
+- def self.event(event, status)
+- case event
+- when EV_HOSTNAME
+- @hostname = status
+- when EV_USERNAME
+- @username = status
+- when EV_PASSWORD
+- @password = status
+- when EV_BUTTON, EV_ACTIVATION
+- # Persistent state not required
+- else
+- raise "Unexpected event: #{event}"
+- end
+-
+- valid = @hostname && @username && @password
+-
+- case @state
+- when UI_STATE_INVALID
+- set_state(UI_STATE_VALID) if valid
+- when UI_STATE_VALID
+- if !valid then
+- set_state(UI_STATE_INVALID)
+- elsif event == EV_BUTTON
+- set_state(UI_STATE_ACTIVATING)
+- end
+- when UI_STATE_ACTIVATING
+- # UI is disabled, so we shouldn't be getting any events other than
+- # EV_ACTIVATION
+- raise "Unexpected event: #{event}" unless event == EV_ACTIVATION
+-
+- set_state(status ? UI_STATE_COMPLETE : UI_STATE_VALID)
+- else
+- raise "Unexpected UI state: #{@state}"
+- end
+- end
+-
+- def self.init(ui, converter)
+- @hostname_ui = ui.get_object('server_hostname')
+- @username_ui = ui.get_object('server_username')
+- @password_ui = ui.get_object('server_password')
+- @connect_frame = ui.get_object('connect_frame')
+- @connect_button = ui.get_object('connect_button')
+- @connect_error = ui.get_object('connect_error')
+-
+- ui.register_handler('server_hostname_changed',
+- method(:server_hostname_changed))
+- ui.register_handler('server_username_changed',
+- method(:server_username_changed))
+- ui.register_handler('server_password_changed',
+- method(:server_password_changed))
+- ui.register_handler('connect_button_clicked',
+- method(:connect_button_clicked))
+-
+- @hostname = @hostname_ui.text.strip.length > 0
+- @username = @username_ui.text.strip.length > 0
+- @password = @password_ui.text.length > 0 # Allow spaces in passwords
+- @state = UI_STATE_INVALID
+-
+- @ui = ui
+- @converter = converter
+- end
+-
+- def self.set_state(state)
+- # Don't do anything if state hasn't changed
+- return if state == @state
+-
+- case state
+- when UI_STATE_INVALID
+- @connect_frame.sensitive = true
+- @connect_button.sensitive = false
+-
+- @state = UI_STATE_INVALID
+- when UI_STATE_VALID
+- @connect_frame.sensitive = true
+- @connect_button.sensitive = true
+-
+- @state = UI_STATE_VALID
+- when UI_STATE_ACTIVATING
+- @connect_frame.sensitive = false
+- @connect_button.sensitive = false
+- @connect_error.text = ''
+-
+- @state = UI_STATE_ACTIVATING
+- when UI_STATE_COMPLETE
+- # Activate the next page
+- @ui.active_page = 'conversion_win'
+-
+- # ... then leave this one as we hope to find it if we come back here
+- set_state(UI_STATE_VALID)
+- else
+- raise "Attempt to set unexpected UI state: #{@state}"
+- end
+- end
+-
+- def self.server_hostname_changed
+- event(EV_HOSTNAME, @hostname_ui.text.strip.length > 0)
+- end
+-
+- def self.server_username_changed
+- event(EV_USERNAME, @username_ui.text.strip.length > 0)
+- end
+-
+- def self.server_password_changed
+- event(EV_PASSWORD, @password_ui.text.length > 0)
+- end
+-
+- def self.connect_button_clicked
+- event(EV_BUTTON, true)
+-
+- hostname = @hostname_ui.text.strip
+- username = @username_ui.text.strip
+- password = @password_ui.text
+- connection = VirtP2V::Connection.new(hostname, username, password) \
+- { |result|
+- case result
+- when true
+- @converter.connection = connection
+- connection.connect { |result|
+- case result
+- when true
+- event(EV_ACTIVATION, true)
+- when VirtP2V::Connection::RemoteError
+- @connect_error.text = _('Failed to start ' +
+- 'virt-p2v-server on remote ' +
+- 'server')
+- event(EV_ACTIVATION, false)
+- else
+- @connect_error.text = result.message
+- event(EV_ACTIVATION, false)
+- end
+- }
+- when VirtP2V::Connection::InvalidHostnameError
+- @connect_error.text = _"Unable to connect to #{hostname}"
+- event(EV_ACTIVATION, false)
+- when VirtP2V::Connection::InvalidCredentialsError
+- @connect_error.text = _"Invalid username/password"
+- event(EV_ACTIVATION, false)
+- else
+- raise result
+- end
+- }
+- end
+-
+-end # module
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/convert.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/convert.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/convert.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/convert.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,422 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'gettext'
+-require 'gtk2'
+-
+-require 'virt-p2v/blockdevice'
+-require 'virt-p2v/netdevice'
+-
+-module VirtP2V::UI::Convert
+- include GetText
+-
+- CONVERT_PROFILE_NAME = 0
+-
+- CONVERT_NETWORK_CONVERT = 0
+- CONVERT_NETWORK_DEVICE = 1
+-
+- CONVERT_FIXED_CONVERT = 0
+- CONVERT_FIXED_DEVICE = 1
+- CONVERT_FIXED_PROGRESS = 2
+-
+- CONVERT_REMOVABLE_CONVERT = 0
+- CONVERT_REMOVABLE_DEVICE = 1
+- CONVERT_REMOVABLE_TYPE = 2
+-
+- UI_STATE_INVALID = 0
+- UI_STATE_VALID = 1
+- UI_STATE_CONNECTING = 2
+- UI_STATE_CONVERTING = 3
+- UI_STATE_COMPLETE = 4
+-
+- EV_VALID = 0
+- EV_BUTTON = 1
+- EV_CONNECTION = 2
+- EV_CONVERTED = 3
+-
+- def self.init(ui, converter)
+- # ListStores
+- @profiles = ui.get_object('convert_profile_list')
+- @nics = ui.get_object('convert_network_list')
+- @fixeds = ui.get_object('convert_fixed_list')
+- @removables = ui.get_object('convert_removable_list')
+-
+- # Widgets
+- @profile = ui.get_object('convert_profile')
+- @name = ui.get_object('convert_name')
+- @cpus = ui.get_object('convert_cpus')
+- @memory = ui.get_object('convert_memory')
+- @editable = ui.get_object('convert_editable')
+- @button = ui.get_object('convert_button')
+- @status = ui.get_object('convert_status')
+-
+- # Get initial values from converter
+- @name.text = converter.name
+- @cpus.text = converter.cpus.to_s
+- @memory.text = (converter.memory / 1024 / 1024).to_s
+-
+- # Populate profiles on connection
+- converter.on_connection { |conn|
+- conn.on_connect { |cb|
+- conn.list_profiles { |profiles|
+- cb.call(RuntimeError.new(_('Remote server does not ' +
+- 'define any profiles in ' +
+- '/etc/virt-v2v.conf'))) \
+- if profiles.kind_of?(Exception) or profiles.empty?
+-
+- selected = @profile.active_iter
+- selected = selected[CONVERT_PROFILE_NAME] \
+- unless selected.nil?
+-
+- @profiles.clear
+- profiles.each { |i|
+- profile = @profiles.append
+- profile[CONVERT_PROFILE_NAME] = i
+- @profile.active_iter = profile if i == selected
+- }
+-
+- cb.call(true)
+- }
+- }
+- }
+-
+- VirtP2V::FixedBlockDevice.all_devices.each { |dev|
+- fixed = @fixeds.append
+- fixed[CONVERT_FIXED_CONVERT] = true
+- fixed[CONVERT_FIXED_DEVICE] = dev.device
+- fixed[CONVERT_FIXED_PROGRESS] = 0
+- }
+-
+- VirtP2V::RemovableBlockDevice.all_devices.each { |dev|
+- rem = @removables.append
+- rem[CONVERT_REMOVABLE_CONVERT] = true
+- rem[CONVERT_REMOVABLE_DEVICE] = dev.device
+- rem[CONVERT_REMOVABLE_TYPE] = dev.type
+- }
+-
+- VirtP2V::NetworkDevice.all_devices.each { |dev|
+- nic = @nics.append
+- nic[CONVERT_NETWORK_CONVERT] = dev.connected
+- nic[CONVERT_NETWORK_DEVICE] = dev.name
+- }
+-
+- # Event handlers
+- ui.register_handler('convert_profile_changed',
+- method(:update_values))
+- ui.register_handler('convert_name_changed',
+- method(:update_values))
+- ui.register_handler('convert_cpus_changed',
+- method(:convert_cpus_changed))
+- ui.register_handler('convert_memory_changed',
+- method(:convert_memory_changed))
+- ui.register_handler('convert_fixed_list_row_changed',
+- method(:convert_fixed_list_row_changed))
+- ui.register_handler('convert_removable_list_row_changed',
+- method(:update_values))
+- ui.register_handler('convert_network_list_row_changed',
+- method(:update_values))
+- ui.register_handler('convert_fixed_select_toggled',
+- method(:convert_fixed_select_toggled))
+- ui.register_handler('convert_removable_select_toggled',
+- method(:convert_removable_select_toggled))
+- ui.register_handler('convert_network_select_toggled',
+- method(:convert_network_select_toggled))
+- ui.register_handler('convert_button_clicked',
+- method(:convert_button_clicked))
+-
+- @state = nil
+- set_state(UI_STATE_INVALID)
+- update_values
+-
+- @ui = ui
+- @converter = converter
+- end
+-
+- def self.event(event, status)
+- case @state
+- when UI_STATE_INVALID
+- case event
+- when EV_VALID
+- set_state(UI_STATE_VALID) if status
+- else
+- raise "Unexpected event: #{@state} #{event}"
+- end
+- when UI_STATE_VALID
+- case event
+- when EV_VALID
+- set_state(UI_STATE_INVALID) if !status
+- when EV_BUTTON
+- if @converter.connection.connected then
+- set_state(UI_STATE_CONVERTING)
+- convert
+- else
+- set_state(UI_STATE_CONNECTING)
+- reconnect
+- end
+- else
+- raise "Unexpected event: #{@state} #{event}"
+- end
+- when UI_STATE_CONNECTING
+- case event
+- when EV_CONNECTION
+- if status then
+- set_state(UI_STATE_CONVERTING)
+- convert
+- else
+- set_state(UI_STATE_VALID)
+- end
+- when EV_VALID
+- # update_values will be called when the profile list is cleared
+- # and repopulated during connection. Untidy, but ignore it.
+- else
+- raise "Unexpected event: #{@state} #{event}" \
+- unless event == EV_CONNECTION
+- end
+- when UI_STATE_CONVERTING
+- case event
+- when EV_CONVERTED
+- if status then
+- set_state(UI_STATE_COMPLETE)
+- else
+- set_state(UI_STATE_VALID)
+- end
+- when EV_VALID
+- # update_values will be called when the list stores are updated.
+- # Untidy, but ignore it
+- else
+- raise "Unexpected event: #{@state} #{event}"
+- end
+- else
+- raise "Unexpected UI state: #{@state}"
+- end
+- end
+-
+- def self.set_state(state)
+- # Don't do anything if state hasn't changed
+- return if state == @state
+- @state = state
+-
+- case @state
+- when UI_STATE_INVALID
+- @editable.sensitive = true
+- @button.sensitive = false
+- when UI_STATE_VALID
+- @editable.sensitive = true
+- @button.sensitive = true
+- when UI_STATE_CONNECTING
+- @status.text = _'Failed to start virt-p2v-server on remote server'
+- @editable.sensitive = false
+- @button.sensitive = false
+- when UI_STATE_CONVERTING
+- @editable.sensitive = false
+- @button.sensitive = false
+- when UI_STATE_COMPLETE
+- @ui.active_page = 'success_win'
+-
+- # ... then leave this one as we hope to find it if we come back here
+- set_state(UI_STATE_VALID)
+- else
+- raise "Attempt to set unexpected UI state: #{@state}"
+- end
+- end
+-
+- def self.convert
+- @converter.convert(
+- # status
+- lambda { |msg|
+- @status.text = msg
+- },
+- # progress
+- lambda { |dev, progress|
+- @fixeds.each { |model, path, iter|
+- next unless iter[CONVERT_FIXED_DEVICE] == dev
+-
+- iter[CONVERT_FIXED_PROGRESS] = progress
+- break
+- }
+- }
+- ) { |result|
+- # N.B. Explicit test against true is required here, as result may be
+- # an Exception, which would also return true if evaluated alone
+- if result == true then
+- @status.text = ''
+- event(EV_CONVERTED, true)
+- else
+- @status.text = result.message
+- event(EV_CONVERTED, false)
+- end
+- }
+- end
+-
+- def self.reconnect
+- @status.text = _('Reconnecting')
+- @converter.connection.connect { |result|
+- if result == true then
+- event(EV_CONNECTION, true)
+- else
+- @status.text =
+- _'Failed to start virt-p2v-server on remote server'
+- event(EV_CONNECTION, false)
+- end
+- }
+- end
+-
+- def self.convert_fixed_list_row_changed(model, path, iter)
+- update_values
+- end
+-
+- class InvalidUIState < StandardError; end
+-
+- def self.update_values
+- valid = nil
+- begin
+- # Check there's a profile selected
+- profile = @profile.active_iter
+- raise InvalidUIState if profile.nil?
+- @converter.profile = profile[CONVERT_PROFILE_NAME]
+-
+- # Check there's a name set
+- name = @name.text
+- raise InvalidUIState if name.nil? || name.strip.length == 0
+- @converter.name = name
+-
+- # Check cpus and memory are set and numeric
+- cpus = @cpus.text
+- raise InvalidUIState if cpus.nil?
+- cpus = Integer(cpus) rescue nil
+- raise InvalidUIState if cpus.nil?
+- @converter.cpus = cpus
+-
+- memory = @memory.text
+- raise InvalidUIState if memory.nil?
+- memory = Integer(memory) rescue nil
+- raise InvalidUIState if memory.nil?
+- @converter.memory = memory * 1024 * 1024
+-
+- # Check that at least 1 fixed storage device is selected
+- fixed = false
+- @converter.disks.clear
+- @fixeds.each { |model, path, iter|
+- if iter[CONVERT_FIXED_CONVERT] then
+- fixed = true
+- @converter.disks << iter[CONVERT_FIXED_DEVICE]
+- end
+- }
+- raise InvalidUIState unless fixed
+-
+- # Populate removables and nics, although these aren't required to be
+- # selected for the ui state to be valid
+- @converter.removables.clear
+- @removables.each { |model, path, iter|
+- if iter[CONVERT_REMOVABLE_CONVERT] then
+- @converter.removables << iter[CONVERT_REMOVABLE_DEVICE]
+- end
+- }
+- @converter.nics.clear
+- @nics.each { |model, path, iter|
+- if iter[CONVERT_NETWORK_CONVERT] then
+- @converter.nics << iter[CONVERT_NETWORK_DEVICE]
+- end
+- }
+- rescue InvalidUIState
+- valid = false
+- end
+- valid = true if valid.nil?
+-
+- event(EV_VALID, valid)
+- end
+-
+- def self.valid?
+- # Check there's a profile selected
+- profile = @profile.active_iter
+- return false if profile.nil?
+-
+- # Check there's a name set
+- name = @name.text
+- return false if name.nil?
+- return false unless name.strip.length > 0
+-
+- # Check cpus and memory are set and numeric
+- cpus = @cpus.text
+- return false if cpus.nil?
+- cpus = Integer(cpus) rescue nil
+- return false if cpus.nil?
+-
+- memory = @memory.text
+- return false if memory.nil?
+- memory = Integer(memory) rescue nil
+- return false if memory.nil?
+-
+- # Check that at least 1 fixed storage device is selected
+- fixed = false
+- @fixeds.each { |model, path, iter|
+- if iter[CONVERT_FIXED_CONVERT] then
+- fixed = true
+- break
+- end
+- }
+- return false unless fixed
+-
+- return true
+- end
+-
+- def self.convert_cpus_changed
+- check_numeric(@cpus)
+- end
+-
+- def self.convert_memory_changed
+- check_numeric(@memory)
+- end
+-
+- def self.check_numeric(widget)
+- value = widget.text
+- if value.nil? ? false : begin
+- value = Integer(value)
+- value > 0
+- rescue
+- false
+- end
+- then
+- widget.secondary_icon_name = nil
+- else
+- widget.secondary_icon_name = 'gtk-dialog-warning'
+- widget.secondary_icon_tooltip_text =
+- _('Value must be an integer greater than 0')
+- end
+-
+- update_values
+- end
+-
+- def self.convert_fixed_select_toggled(widget, path)
+- iter = @fixeds.get_iter(path)
+- iter[CONVERT_FIXED_CONVERT] = !iter[CONVERT_FIXED_CONVERT]
+- end
+-
+- def self.convert_removable_select_toggled(widget, path)
+- iter = @removables.get_iter(path)
+- iter[CONVERT_REMOVABLE_CONVERT] = !iter[CONVERT_REMOVABLE_CONVERT]
+- end
+-
+- def self.convert_network_select_toggled(widget, path)
+- iter = @nics.get_iter(path)
+- iter[CONVERT_NETWORK_CONVERT] = !iter[CONVERT_NETWORK_CONVERT]
+- end
+-
+- def self.convert_button_clicked
+- event(EV_BUTTON, true)
+- end
+-
+-end # module
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/main.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/main.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/main.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/main.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,110 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'gtk2'
+-require 'virt-p2v/gtk-queue'
+-
+-module VirtP2V
+-module UI
+-
+-class Main
+- def get_object(name)
+- o = @builder.get_object(name)
+- raise "Object #{name} not found in ui" unless o != nil
+-
+- return o
+- end
+-
+- def show
+- @builder.connect_signals { |signal|
+- raise "No hander for signal #{signal}" \
+- unless @signal_handlers.has_key?(signal)
+-
+- @signal_handlers[signal]
+- }
+-
+- # Display the main window
+- main = self.get_object('main_window')
+- main.show_all()
+- end
+-
+- def register_handler(signal, handler)
+- @signal_handlers[signal] = handler
+- end
+-
+- def main_loop
+- Gtk.main_with_queue 100
+- end
+-
+- def active_page=(name)
+- raise "Attempt to activate non-existent page #{name}" \
+- unless @pages.has_key?(name)
+-
+- page = @pages[name]
+-
+- @page_vbox = self.get_object('page_vbox') unless defined? @page_vbox
+- @page_vbox.remove(@selected) if defined? @selected
+- @page_vbox.add(page)
+- @selected = page
+- end
+-
+- def active_page
+- return @selected
+- end
+-
+- def quit
+- Gtk.main_quit()
+- end
+-
+- private
+-
+- def initialize
+- @builder = Gtk::Builder.new()
+-
+- # Find the UI definition in $LOAD_PATH
+- i = $LOAD_PATH.index { |path|
+- File.exists?(path + '/virt-p2v/ui/p2v.ui')
+- }
+- @builder.add_from_file($LOAD_PATH[i] + '/virt-p2v/ui/p2v.ui')
+-
+- @signal_handlers = {}
+- self.register_handler('gtk_main_quit', method(:quit))
+-
+- # Configure the Wizard page frame
+- # Can't change these colours from glade for some reason
+- self.get_object('title_background').
+- modify_bg(Gtk::STATE_NORMAL, Gdk::Color.parse('#86ABD9'))
+- self.get_object('page_frame').
+- modify_fg(Gtk::STATE_NORMAL, Gdk::Color.parse('#86ABD9'))
+-
+- # Load all pages from glade
+- @pages = {}
+- [ 'network_win', 'server_win',
+- 'conversion_win', 'success_win' ].each { |name|
+- page = self.get_object(name)
+-
+- child = page.children[0]
+- page.remove(child)
+- @pages[name] = child
+- }
+-
+- # Set a default first page
+- self.active_page = 'network_win'
+- end
+-end
+-
+-end # UI
+-end # VirtP2V
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/network.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/network.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/network.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/network.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,317 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'gettext'
+-require 'gtk2'
+-require 'ipaddr'
+-require 'virt-p2v/netdevice'
+-
+-module VirtP2V::UI::Network
+- include GetText
+-
+- # The indices of Device List colums, taken from glade
+- DEVCOL_NAME = 0
+- DEVCOL_MAC = 1
+- DEVCOL_STATUS = 2
+- DEVCOL_AVAILABLE = 3
+-
+- UI_STATE_INVALID = 0
+- UI_STATE_VALID = 1
+- UI_STATE_ACTIVATING = 2
+- UI_STATE_COMPLETE = 3
+-
+- EV_IP_CONFIG = 0
+- EV_SELECTION = 1
+- EV_BUTTON = 2
+- EV_ACTIVATION = 3
+-
+- def self.event(event, status)
+- case event
+- when EV_IP_CONFIG
+- @ip_config = status
+- when EV_SELECTION
+- @selected = status
+- when EV_BUTTON, EV_ACTIVATION
+- # Persistent state not required
+- else
+- raise "Unexpected NetworkConfig event: #{event}"
+- end
+-
+- case @state
+- when UI_STATE_INVALID
+- if @ip_config && @selected then
+- set_state(UI_STATE_VALID)
+- end
+- when UI_STATE_VALID
+- if !@ip_config || !@selected then
+- set_state(UI_STATE_INVALID)
+- elsif event == EV_BUTTON
+- set_state(UI_STATE_ACTIVATING)
+- end
+- when UI_STATE_ACTIVATING
+- # UI is disabled and we're waiting for EV_ACTIVATION, but we could
+- # also get events triggered by NetworkManager signals.
+-
+- if event == EV_ACTIVATION then
+- if status then
+- set_state(UI_STATE_COMPLETE)
+- else
+- set_state(UI_STATE_VALID)
+- end
+- elsif !@ip_config || !@selected then
+- set_state(UI_STATE_INVALID)
+- end
+- else
+- raise "Unexpected NetworkConfig UI state: #{@state}"
+- end
+- end
+-
+- def self.init(ui)
+- # Configure initial defaults
+- @manual_mode = false
+- @ip_address = nil
+- @ip_prefix = nil
+- @ip_gateway = nil
+- @ip_dns = nil
+- @state = UI_STATE_INVALID
+- @ip_config = false
+- @selected = false
+-
+- @network_button = ui.get_object('network_button')
+- @device_list_frame = ui.get_object('device_list_frame')
+- @ipv4_config_frame = ui.get_object('ipv4_config_frame')
+- @dl_selection = ui.get_object('network_device_list_view').
+- selection
+- @device_list = ui.get_object('network_device_list')
+- @manual_ui = ui.get_object('ip_manual')
+- @ip_address_ui = ui.get_object('ip_address')
+- @ip_prefix_ui = ui.get_object('ip_prefix')
+- @ip_gateway_ui = ui.get_object('ip_gateway')
+- @ip_dns_ui = ui.get_object('ip_dns')
+-
+- ui.register_handler('network_button_clicked',
+- method(:network_button_clicked))
+- ui.register_handler('ip_auto_toggled',
+- method(:ip_auto_toggled))
+- ui.register_handler('ip_address_changed',
+- method(:ip_address_changed))
+- ui.register_handler('ip_prefix_changed',
+- method(:ip_prefix_changed))
+- ui.register_handler('ip_gateway_changed',
+- method(:ip_gateway_changed))
+- ui.register_handler('ip_dns_changed',
+- method(:ip_dns_changed))
+-
+- check_config_valid()
+-
+- # The user may only select a single device
+- @dl_selection.mode = Gtk::SELECTION_SINGLE
+-
+- @dl_selection.set_select_function { |selection, model, path, current|
+- iter = model.get_iter(path)
+-
+- # This is a toggle event. The new state is the opposite of the
+- # current state
+- new_state = !current
+-
+- # Don't allow the user to select an unavailable device
+- if new_state then
+- # Notify the config UI if we're selecting a device
+- if iter[DEVCOL_AVAILABLE] then
+- event(EV_SELECTION, true)
+- end
+-
+- iter[DEVCOL_AVAILABLE]
+-
+- # Always allow the user to unselect a device
+- else
+- # Notify the UI that we're unselecting the device
+- event(EV_SELECTION, false)
+- true
+- end
+- }
+-
+- # Store a map of device names to row references
+- refs = {}
+-
+- # Populate the device list with all detected network devices
+- VirtP2V::NetworkDevice.all_devices.each { |device|
+- iter = @device_list.append()
+-
+- iter[DEVCOL_NAME] = device.name
+- iter[DEVCOL_MAC] = device.mac
+- iter[DEVCOL_STATUS] = device.state
+- iter[DEVCOL_AVAILABLE] = device.connected
+-
+- # Store a stable reference to this row in the TreeModel
+- refs[device.name] =
+- Gtk::TreeRowReference.new(@device_list, iter.path)
+- }
+-
+- # Listen for updates to device states
+- VirtP2V::NetworkDevice.add_listener( lambda { |device|
+- path = refs[device.name].path
+-
+- iter = @device_list.get_iter(path)
+- iter[DEVCOL_STATUS] = device.state
+- iter[DEVCOL_AVAILABLE] = device.connected
+-
+- # Notify the UI that a device was activated
+- event(EV_ACTIVATION, device.activated) \
+- unless device.activated.nil?
+-
+- # Unselect the path if it was previously selected and is no
+- # longer available
+- if !device.connected && @dl_selection.iter_is_selected?(iter)
+- then
+- @dl_selection.unselect_all()
+- event(EV_SELECTION, false)
+- end
+- } )
+-
+- @ui = ui
+- end
+-
+- def self.set_state(state)
+- # Don't do anything if state hasn't changed
+- return if state == @state
+-
+- case state
+- when UI_STATE_INVALID
+- @network_button.sensitive = false
+- @device_list_frame.sensitive = true
+- @ipv4_config_frame.sensitive = true
+-
+- @state = UI_STATE_INVALID
+- when UI_STATE_VALID
+- @network_button.sensitive = true
+- @device_list_frame.sensitive = true
+- @ipv4_config_frame.sensitive = true
+-
+- @state = UI_STATE_VALID
+- when UI_STATE_ACTIVATING
+- @network_button.sensitive = false
+- @device_list_frame.sensitive = false
+- @ipv4_config_frame.sensitive = false
+-
+- @state = UI_STATE_ACTIVATING
+- when UI_STATE_COMPLETE
+- # Activate the next page
+- @ui.active_page = 'server_win'
+-
+- # ... then leave this one as we hope to find it if we come back here
+- set_state(UI_STATE_VALID)
+- else
+- raise "Attempt to set unexected NetworkConfig UI state: #{@state}"
+- end
+- end
+-
+- def self.network_button_clicked
+- event(EV_BUTTON, true)
+-
+- iter = @dl_selection.selected
+- return if iter.nil? # Shouldn't be possible
+- name = iter[DEVCOL_NAME]
+-
+- VirtP2V::NetworkDevice[name].activate(!@manual_mode, @ip_address,
+- @ip_prefix, @ip_gateway, @ip_dns)
+- end
+-
+- def self.ip_auto_toggled
+- @manual_mode = !@manual_mode
+- @manual_ui.sensitive = @manual_mode
+-
+- check_config_valid()
+- end
+-
+- def self.ip_address_changed
+- @ip_address = parse_ip(@ip_address_ui)
+-
+- check_config_valid()
+- end
+-
+- # Check IP prefix is a positive integer
+- # We check that it's appropriate to the address class in use elsewhere
+- def self.ip_prefix_changed
+- begin
+- @ip_prefix = Integer(@ip_prefix_ui.text)
+- rescue ArgumentError => e
+- # Ignore the result if it didn't parse
+- @ip_prefix = nil
+- return
+- end
+-
+- if @ip_prefix < 0 then
+- @ip_prefix = nil
+- end
+-
+- check_config_valid()
+- end
+-
+- def self.ip_gateway_changed
+- @ip_gateway = parse_ip(@ip_gateway_ui)
+-
+- check_config_valid()
+- end
+-
+- # Parse an IP address understood by IPAddr
+- def self.parse_ip(entry)
+- a = entry.text.strip
+-
+- begin
+- ip = IPAddr.new(a)
+- rescue ArgumentError => e
+- # Ignore the result if it didn't parse
+- ip = nil
+- end
+-
+- return ip
+- end
+-
+- def self.ip_dns_changed
+- dns = @ip_dns_ui.text
+-
+- @ip_dns = []
+- dns.split(/\s*,+\s*/).each { |entry|
+- begin
+- @ip_dns << IPAddr.new(entry)
+- rescue ArgumentError => e
+- @ip_dns = ()
+- break
+- end
+- }
+- end
+-
+- def self.check_config_valid
+- if !@manual_mode || (!@ip_address.nil? &&
+- !@ip_prefix.nil? &&
+- !@ip_gateway.nil?) then
+- if @manual_mode then
+- # Check that IPv4/IPv6 is used consistently
+- if @ip_address.ipv4? then
+- event(EV_IP_CONFIG, @ip_gateway.ipv4? && @ip_prefix < 32)
+- else
+- event(EV_IP_CONFIG, @ip_gateway.ipv6? && @ip_prefix < 128)
+- end
+- else
+- event(EV_IP_CONFIG, true)
+- end
+- else
+- event(EV_IP_CONFIG, false)
+- end
+- end
+-
+-end # module
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/p2v.ui virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/p2v.ui
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/p2v.ui 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/p2v.ui 1970-01-01 01:00:00.000000000 +0100
+@@ -1,1031 +0,0 @@
+-<?xml version="1.0"?>
+-<interface>
+- <requires lib="gtk+" version="2.16"/>
+- <!-- interface-naming-policy project-wide -->
+- <object class="GtkWindow" id="main_window">
+- <property name="resizable">False</property>
+- <property name="window_position">center-always</property>
+- <property name="decorated">False</property>
+- <signal name="destroy" handler="gtk_main_quit"/>
+- <child>
+- <object class="GtkAlignment" id="alignment2">
+- <property name="visible">True</property>
+- <property name="xscale">0</property>
+- <property name="yscale">0</property>
+- <child>
+- <object class="GtkFrame" id="page_frame">
+- <property name="width_request">800</property>
+- <property name="height_request">600</property>
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="label_yalign">0</property>
+- <property name="shadow_type">in</property>
+- <child>
+- <object class="GtkVBox" id="page_vbox">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <property name="spacing">2</property>
+- <child>
+- <object class="GtkEventBox" id="title_background">
+- <property name="visible">True</property>
+- <child>
+- <object class="GtkLabel" id="title_label">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="yalign">0</property>
+- <property name="xpad">5</property>
+- <property name="ypad">5</property>
+- <property name="label"><span weight='bold' foreground='white' size='xx-large'>virt-p2v</span></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <placeholder/>
+- </child>
+- </object>
+- </child>
+- <child type="label_item">
+- <placeholder/>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- <object class="GtkListStore" id="network_device_list">
+- <columns>
+- <!-- column-name Name -->
+- <column type="gchararray"/>
+- <!-- column-name MAC -->
+- <column type="gchararray"/>
+- <!-- column-name Status -->
+- <column type="gchararray"/>
+- <!-- column-name Available -->
+- <column type="gboolean"/>
+- </columns>
+- </object>
+- <object class="GtkListStore" id="convert_network_list">
+- <columns>
+- <!-- column-name Convert -->
+- <column type="gboolean"/>
+- <!-- column-name Device -->
+- <column type="gchararray"/>
+- </columns>
+- <signal name="row_changed" handler="convert_network_list_row_changed"/>
+- </object>
+- <object class="GtkListStore" id="convert_fixed_list">
+- <columns>
+- <!-- column-name Convert -->
+- <column type="gboolean"/>
+- <!-- column-name Device -->
+- <column type="gchararray"/>
+- <!-- column-name Progress -->
+- <column type="gdouble"/>
+- </columns>
+- <signal name="row_changed" handler="convert_fixed_list_row_changed"/>
+- </object>
+- <object class="GtkListStore" id="convert_removable_list">
+- <columns>
+- <!-- column-name Convert -->
+- <column type="gboolean"/>
+- <!-- column-name Device -->
+- <column type="gchararray"/>
+- <!-- column-name Type -->
+- <column type="gchararray"/>
+- </columns>
+- <signal name="row_changed" handler="convert_removable_list_row_changed"/>
+- </object>
+- <object class="GtkListStore" id="convert_profile_list">
+- <columns>
+- <!-- column-name Name -->
+- <column type="gchararray"/>
+- </columns>
+- </object>
+- <object class="GtkWindow" id="network_win">
+- <property name="width_request">800</property>
+- <property name="height_request">550</property>
+- <child>
+- <object class="GtkVBox" id="vbox1">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <child>
+- <object class="GtkLabel" id="label1">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="yalign">1</property>
+- <property name="ypad">11</property>
+- <property name="label" translatable="yes">Welcome to virt-p2v.</property>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkFrame" id="device_list_frame">
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">out</property>
+- <child>
+- <object class="GtkScrolledWindow" id="scrolledwindow1">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="hscrollbar_policy">automatic</property>
+- <property name="vscrollbar_policy">automatic</property>
+- <child>
+- <object class="GtkTreeView" id="network_device_list_view">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="model">network_device_list</property>
+- <property name="headers_clickable">False</property>
+- <property name="search_column">0</property>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+- <property name="title">Device</property>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext1"/>
+- <attributes>
+- <attribute name="sensitive">3</attribute>
+- <attribute name="text">0</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+- <property name="fixed_width">18</property>
+- <property name="title">MAC Address</property>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext3"/>
+- <attributes>
+- <attribute name="sensitive">3</attribute>
+- <attribute name="text">1</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+- <property name="title">Status</property>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext2"/>
+- <attributes>
+- <attribute name="sensitive">3</attribute>
+- <attribute name="text">2</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label5">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes"><b>Select a network device</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkFrame" id="ipv4_config_frame">
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">in</property>
+- <child>
+- <object class="GtkAlignment" id="alignment1">
+- <property name="visible">True</property>
+- <property name="left_padding">12</property>
+- <child>
+- <object class="GtkVBox" id="vbox2">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <child>
+- <object class="GtkCheckButton" id="ip_auto">
+- <property name="label" translatable="yes">Automatic configuration</property>
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="receives_default">False</property>
+- <property name="active">True</property>
+- <property name="draw_indicator">True</property>
+- <signal name="toggled" handler="ip_auto_toggled"/>
+- </object>
+- <packing>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkTable" id="ip_manual">
+- <property name="visible">True</property>
+- <property name="sensitive">False</property>
+- <property name="n_rows">3</property>
+- <property name="n_columns">2</property>
+- <property name="column_spacing">2</property>
+- <child>
+- <object class="GtkLabel" id="label3">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">IP Address:</property>
+- </object>
+- <packing>
+- <property name="x_options">GTK_FILL</property>
+- <property name="y_options">GTK_FILL</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label8">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Gateway:</property>
+- </object>
+- <packing>
+- <property name="top_attach">1</property>
+- <property name="bottom_attach">2</property>
+- <property name="x_options">GTK_FILL</property>
+- <property name="y_options">GTK_FILL</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label4">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">DNS Servers:</property>
+- </object>
+- <packing>
+- <property name="top_attach">2</property>
+- <property name="bottom_attach">3</property>
+- <property name="x_options">GTK_FILL</property>
+- <property name="y_options">GTK_FILL</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="ip_gateway">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="max_length">39</property>
+- <property name="width_chars">39</property>
+- <property name="truncate_multiline">True</property>
+- <signal name="changed" handler="ip_gateway_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="top_attach">1</property>
+- <property name="bottom_attach">2</property>
+- <property name="y_options">GTK_FILL</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="ip_dns">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="width_chars">35</property>
+- <signal name="changed" handler="ip_dns_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="top_attach">2</property>
+- <property name="bottom_attach">3</property>
+- <property name="y_options">GTK_FILL</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkHBox" id="hbox6">
+- <property name="visible">True</property>
+- <property name="spacing">2</property>
+- <child>
+- <object class="GtkEntry" id="ip_address">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="max_length">39</property>
+- <property name="width_chars">39</property>
+- <property name="truncate_multiline">True</property>
+- <signal name="changed" handler="ip_address_changed"/>
+- </object>
+- <packing>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label7">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Prefix:</property>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="ip_prefix">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="max_length">2</property>
+- <property name="width_chars">2</property>
+- <property name="truncate_multiline">True</property>
+- <signal name="changed" handler="ip_prefix_changed"/>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">2</property>
+- </packing>
+- </child>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="y_options">GTK_FILL</property>
+- </packing>
+- </child>
+- </object>
+- <packing>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label2">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes"><b>IP Configuration</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">2</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkAlignment" id="alignment3">
+- <property name="visible">True</property>
+- <property name="xalign">1</property>
+- <property name="xscale">0</property>
+- <child>
+- <object class="GtkButton" id="network_button">
+- <property name="label" translatable="yes">Use these network settings</property>
+- <property name="visible">True</property>
+- <property name="sensitive">False</property>
+- <property name="can_focus">True</property>
+- <property name="receives_default">True</property>
+- <signal name="clicked" handler="network_button_clicked"/>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">3</property>
+- </packing>
+- </child>
+- </object>
+- </child>
+- </object>
+- <object class="GtkWindow" id="server_win">
+- <child>
+- <object class="GtkVBox" id="vbox3">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <child>
+- <object class="GtkAlignment" id="alignment4">
+- <property name="visible">True</property>
+- <property name="xscale">0</property>
+- <property name="yscale">0</property>
+- <child>
+- <object class="GtkFrame" id="connect_frame">
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">in</property>
+- <child>
+- <object class="GtkAlignment" id="alignment9">
+- <property name="visible">True</property>
+- <property name="left_padding">12</property>
+- <child>
+- <object class="GtkVBox" id="vbox5">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <child>
+- <object class="GtkTable" id="table1">
+- <property name="visible">True</property>
+- <property name="n_rows">3</property>
+- <property name="n_columns">2</property>
+- <property name="column_spacing">2</property>
+- <child>
+- <object class="GtkLabel" id="label9">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Hostname:</property>
+- </object>
+- <packing>
+- <property name="x_options"></property>
+- <property name="y_options"></property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label10">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Username:</property>
+- </object>
+- <packing>
+- <property name="top_attach">1</property>
+- <property name="bottom_attach">2</property>
+- <property name="x_options"></property>
+- <property name="y_options"></property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label11">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Password:</property>
+- </object>
+- <packing>
+- <property name="top_attach">2</property>
+- <property name="bottom_attach">3</property>
+- <property name="x_options"></property>
+- <property name="y_options"></property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="server_hostname">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="invisible_char">•</property>
+- <property name="width_chars">40</property>
+- <signal name="changed" handler="server_hostname_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="y_options"></property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="server_password">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="visibility">False</property>
+- <property name="invisible_char">•</property>
+- <property name="width_chars">40</property>
+- <signal name="changed" handler="server_password_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="top_attach">2</property>
+- <property name="bottom_attach">3</property>
+- <property name="y_options"></property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="server_username">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="invisible_char">•</property>
+- <property name="width_chars">40</property>
+- <property name="text" translatable="yes">root</property>
+- <signal name="changed" handler="server_username_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="top_attach">1</property>
+- <property name="bottom_attach">2</property>
+- <property name="y_options"></property>
+- </packing>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="connect_error">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="yalign">0</property>
+- <property name="xpad">8</property>
+- <property name="ypad">8</property>
+- <attributes>
+- <attribute name="foreground" value="#ffff00000000"/>
+- </attributes>
+- </object>
+- <packing>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label6">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes"><b>Connect to conversion server</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkAlignment" id="alignment5">
+- <property name="visible">True</property>
+- <property name="xalign">1</property>
+- <property name="yalign">0</property>
+- <property name="xscale">0</property>
+- <property name="yscale">0</property>
+- <child>
+- <object class="GtkButton" id="connect_button">
+- <property name="label" translatable="yes">Connect</property>
+- <property name="visible">True</property>
+- <property name="sensitive">False</property>
+- <property name="can_focus">True</property>
+- <property name="receives_default">True</property>
+- <signal name="clicked" handler="connect_button_clicked"/>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- </object>
+- </child>
+- </object>
+- <object class="GtkWindow" id="conversion_win">
+- <child>
+- <object class="GtkVBox" id="vbox4">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <child>
+- <object class="GtkHBox" id="convert_editable">
+- <property name="visible">True</property>
+- <child>
+- <object class="GtkFrame" id="frame2">
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">out</property>
+- <child>
+- <object class="GtkAlignment" id="alignment6">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="yalign">0</property>
+- <property name="xscale">0</property>
+- <property name="yscale">0</property>
+- <property name="left_padding">12</property>
+- <child>
+- <object class="GtkTable" id="table2">
+- <property name="visible">True</property>
+- <property name="n_rows">4</property>
+- <property name="n_columns">2</property>
+- <property name="column_spacing">2</property>
+- <child>
+- <object class="GtkLabel" id="label14">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Destination Profile:</property>
+- </object>
+- </child>
+- <child>
+- <object class="GtkComboBox" id="convert_profile">
+- <property name="visible">True</property>
+- <property name="model">convert_profile_list</property>
+- <signal name="changed" handler="convert_profile_changed"/>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext8"/>
+- <attributes>
+- <attribute name="text">0</attribute>
+- </attributes>
+- </child>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label16">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Memory (MB):</property>
+- </object>
+- <packing>
+- <property name="top_attach">3</property>
+- <property name="bottom_attach">4</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="convert_memory">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="invisible_char">•</property>
+- <property name="truncate_multiline">True</property>
+- <signal name="changed" handler="convert_memory_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="top_attach">3</property>
+- <property name="bottom_attach">4</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label15">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Number of CPUs:</property>
+- </object>
+- <packing>
+- <property name="top_attach">2</property>
+- <property name="bottom_attach">3</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkLabel" id="label18">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="label" translatable="yes">Name</property>
+- </object>
+- <packing>
+- <property name="top_attach">1</property>
+- <property name="bottom_attach">2</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="convert_name">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="invisible_char">•</property>
+- <property name="truncate_multiline">True</property>
+- <signal name="changed" handler="convert_name_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="top_attach">1</property>
+- <property name="bottom_attach">2</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkEntry" id="convert_cpus">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="invisible_char">•</property>
+- <property name="truncate_multiline">True</property>
+- <signal name="changed" handler="convert_cpus_changed"/>
+- </object>
+- <packing>
+- <property name="left_attach">1</property>
+- <property name="right_attach">2</property>
+- <property name="top_attach">2</property>
+- <property name="bottom_attach">3</property>
+- </packing>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label13">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes"><b>Target properties</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="fill">False</property>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkVBox" id="vbox6">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <child>
+- <object class="GtkFrame" id="frame3">
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">out</property>
+- <child>
+- <object class="GtkAlignment" id="alignment8">
+- <property name="visible">True</property>
+- <child>
+- <object class="GtkScrolledWindow" id="scrolledwindow2">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="hscrollbar_policy">automatic</property>
+- <property name="vscrollbar_policy">automatic</property>
+- <child>
+- <object class="GtkTreeView" id="treeview1">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="model">convert_fixed_list</property>
+- <property name="headers_clickable">False</property>
+- <property name="search_column">0</property>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+- <property name="title">Convert</property>
+- <property name="clickable">True</property>
+- <child>
+- <object class="GtkCellRendererToggle" id="convert_fixed_select">
+- <signal name="toggled" handler="convert_fixed_select_toggled"/>
+- </object>
+- <attributes>
+- <attribute name="active">0</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn5">
+- <property name="title">Device</property>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext4"/>
+- <attributes>
+- <attribute name="text">1</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn8">
+- <property name="title">Transfer Progress</property>
+- <property name="expand">True</property>
+- <child>
+- <object class="GtkCellRendererProgress" id="cellrendererprogress1"/>
+- <attributes>
+- <attribute name="value">2</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label17">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes"><b>Fixed Storage</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkFrame" id="frame4">
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">out</property>
+- <child>
+- <object class="GtkAlignment" id="alignment11">
+- <property name="visible">True</property>
+- <child>
+- <object class="GtkScrolledWindow" id="scrolledwindow4">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="hscrollbar_policy">automatic</property>
+- <property name="vscrollbar_policy">automatic</property>
+- <child>
+- <object class="GtkTreeView" id="treeview3">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="model">convert_removable_list</property>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn9">
+- <property name="title">Convert</property>
+- <child>
+- <object class="GtkCellRendererToggle" id="convert_removable_select">
+- <signal name="toggled" handler="convert_removable_select_toggled"/>
+- </object>
+- <attributes>
+- <attribute name="active">0</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn10">
+- <property name="title">Device</property>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext6"/>
+- <attributes>
+- <attribute name="text">1</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn11">
+- <property name="title">Type</property>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext7"/>
+- <attributes>
+- <attribute name="text">2</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label19">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes"><b>Removable Media</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkFrame" id="frame1">
+- <property name="visible">True</property>
+- <property name="label_xalign">0</property>
+- <property name="shadow_type">out</property>
+- <child>
+- <object class="GtkAlignment" id="alignment10">
+- <property name="visible">True</property>
+- <property name="xalign">1</property>
+- <property name="yalign">1</property>
+- <child>
+- <object class="GtkScrolledWindow" id="scrolledwindow3">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="hscrollbar_policy">automatic</property>
+- <property name="vscrollbar_policy">automatic</property>
+- <child>
+- <object class="GtkTreeView" id="treeview2">
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="model">convert_network_list</property>
+- <property name="headers_clickable">False</property>
+- <property name="search_column">0</property>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn6">
+- <property name="title">Convert</property>
+- <child>
+- <object class="GtkCellRendererToggle" id="convert_network_select">
+- <signal name="toggled" handler="convert_network_select_toggled"/>
+- </object>
+- <attributes>
+- <attribute name="active">0</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- <child>
+- <object class="GtkTreeViewColumn" id="treeviewcolumn7">
+- <property name="title">Device</property>
+- <child>
+- <object class="GtkCellRendererText" id="cellrenderertext5"/>
+- <attributes>
+- <attribute name="text">1</attribute>
+- </attributes>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- </object>
+- </child>
+- <child type="label">
+- <object class="GtkLabel" id="label12">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes"><b>Network Interfaces</b></property>
+- <property name="use_markup">True</property>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="position">2</property>
+- </packing>
+- </child>
+- </object>
+- <packing>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- </object>
+- <packing>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkHBox" id="hbox1">
+- <property name="visible">True</property>
+- <child>
+- <object class="GtkLabel" id="convert_status">
+- <property name="visible">True</property>
+- <property name="xalign">0</property>
+- <property name="xpad">12</property>
+- <attributes>
+- <attribute name="foreground" value="#ffff00000000"/>
+- </attributes>
+- </object>
+- <packing>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkButton" id="convert_button">
+- <property name="label" translatable="yes">Convert</property>
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="receives_default">True</property>
+- <signal name="clicked" handler="convert_button_clicked"/>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="fill">False</property>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- </object>
+- <packing>
+- <property name="expand">False</property>
+- <property name="fill">False</property>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- </object>
+- </child>
+- </object>
+- <object class="GtkWindow" id="success_win">
+- <child>
+- <object class="GtkVBox" id="vbox7">
+- <property name="visible">True</property>
+- <property name="orientation">vertical</property>
+- <child>
+- <object class="GtkLabel" id="label20">
+- <property name="visible">True</property>
+- <property name="label" translatable="yes">A guest has been successfully created on the target server.
+-
+-Remove the temporary boot device from this machine and press 'Reboot' to continue.</property>
+- <property name="justify">center</property>
+- </object>
+- <packing>
+- <property name="position">0</property>
+- </packing>
+- </child>
+- <child>
+- <object class="GtkAlignment" id="alignment7">
+- <property name="visible">True</property>
+- <property name="xscale">0.25</property>
+- <property name="yscale">0.25</property>
+- <child>
+- <object class="GtkButton" id="reboot_button">
+- <property name="label" translatable="yes">Reboot</property>
+- <property name="visible">True</property>
+- <property name="can_focus">True</property>
+- <property name="receives_default">True</property>
+- <signal name="clicked" handler="reboot_button_clicked"/>
+- </object>
+- </child>
+- </object>
+- <packing>
+- <property name="position">1</property>
+- </packing>
+- </child>
+- </object>
+- </child>
+- </object>
+-</interface>
+diff -ruN virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/success.rb virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/success.rb
+--- virt-v2v-v0.8.1/p2v-client/lib/virt-p2v/ui/success.rb 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/lib/virt-p2v/ui/success.rb 1970-01-01 01:00:00.000000000 +0100
+@@ -1,33 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'gettext'
+-
+-module VirtP2V::UI::Success
+- include GetText
+-
+- def self.init(ui)
+- ui.register_handler('reboot_button_clicked',
+- method(:reboot_button_clicked))
+-
+- @ui = ui
+- end
+-
+- def self.reboot_button_clicked
+- @ui.quit
+- end
+-
+-end # module
+diff -ruN virt-v2v-v0.8.1/p2v-client/Manifest virt-v2v-v0.8.1.new/p2v-client/Manifest
+--- virt-v2v-v0.8.1/p2v-client/Manifest 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/Manifest 1970-01-01 01:00:00.000000000 +0100
+@@ -1,15 +0,0 @@
+-Rakefile
+-bin/virt-p2v
+-lib/virt-p2v/blockdevice.rb
+-lib/virt-p2v/connection.rb
+-lib/virt-p2v/converter.rb
+-lib/virt-p2v/gtk-queue.rb
+-lib/virt-p2v/netdevice.rb
+-lib/virt-p2v/ui/connect.rb
+-lib/virt-p2v/ui/convert.rb
+-lib/virt-p2v/ui/main.rb
+-lib/virt-p2v/ui/network.rb
+-lib/virt-p2v/ui/p2v.ui
+-lib/virt-p2v/ui/success.rb
+-virt-p2v.gemspec
+-Manifest
+diff -ruN virt-v2v-v0.8.1/p2v-client/Rakefile virt-v2v-v0.8.1.new/p2v-client/Rakefile
+--- virt-v2v-v0.8.1/p2v-client/Rakefile 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/Rakefile 1970-01-01 01:00:00.000000000 +0100
+@@ -1,37 +0,0 @@
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-require 'rubygems'
+-require 'echoe'
+-
+-Echoe.new("virt-p2v") do |p|
+- p.project = "Virt P2V"
+- p.version = `../Build version`
+- p.author = "Matthew Booth"
+- p.summary = "Send a machine's storage and metadata to virt-p2v-server"
+- p.description = <<EOF
+-virt-p2v is a client which connects to a virt-p2v-server and transfer's the host
+-machine's storage and metadata. virt-p2v is intended to be run from a live
+-image, so it is unlikely you want to install it.
+-EOF
+- p.url = "http://libguestfs.org"
+- p.email = "libguestfs at redhat.com"
+- p.runtime_dependencies = [
+- 'gtk2',
+- 'gettext',
+- 'net-ssh'
+- ]
+-end
+diff -ruN virt-v2v-v0.8.1/p2v-client/virt-p2v.gemspec virt-v2v-v0.8.1.new/p2v-client/virt-p2v.gemspec
+--- virt-v2v-v0.8.1/p2v-client/virt-p2v.gemspec 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-client/virt-p2v.gemspec 1970-01-01 01:00:00.000000000 +0100
+@@ -1,44 +0,0 @@
+-# -*- encoding: utf-8 -*-
+-
+-Gem::Specification.new do |s|
+- s.name = %q{virt-p2v}
+- s.version = "0.7.1"
+-
+- s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
+- s.authors = ["Matthew Booth"]
+- s.date = %q{2011-04-15}
+- s.default_executable = %q{virt-p2v}
+- s.description = %q{virt-p2v is a client which connects to a virt-p2v-server and transfer's the host
+-machine's storage and metadata. virt-p2v is intended to be run from a live
+-image, so it is unlikely you want to install it.
+-}
+- s.email = %q{libguestfs at redhat.com}
+- s.executables = ["virt-p2v"]
+- s.extra_rdoc_files = ["COPYING", "bin/virt-p2v", "lib/virt-p2v/blockdevice.rb", "lib/virt-p2v/connection.rb", "lib/virt-p2v/converter.rb", "lib/virt-p2v/gtk-queue.rb", "lib/virt-p2v/netdevice.rb", "lib/virt-p2v/ui/connect.rb", "lib/virt-p2v/ui/convert.rb", "lib/virt-p2v/ui/main.rb", "lib/virt-p2v/ui/network.rb", "lib/virt-p2v/ui/p2v.ui", "lib/virt-p2v/ui/success.rb"]
+- s.files = ["COPYING", "Rakefile", "bin/virt-p2v", "lib/virt-p2v/blockdevice.rb", "lib/virt-p2v/connection.rb", "lib/virt-p2v/converter.rb", "lib/virt-p2v/gtk-queue.rb", "lib/virt-p2v/netdevice.rb", "lib/virt-p2v/ui/connect.rb", "lib/virt-p2v/ui/convert.rb", "lib/virt-p2v/ui/main.rb", "lib/virt-p2v/ui/network.rb", "lib/virt-p2v/ui/p2v.ui", "lib/virt-p2v/ui/success.rb", "virt-p2v.gemspec", "Manifest"]
+- s.homepage = %q{http://libguestfs.org}
+- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Virt-p2v"]
+- s.require_paths = ["lib"]
+- s.rubyforge_project = %q{Virt P2V}
+- s.rubygems_version = %q{1.3.7}
+- s.summary = %q{Send a machine's storage and metadata to virt-p2v-server}
+-
+- if s.respond_to? :specification_version then
+- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+- s.specification_version = 3
+-
+- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+- s.add_runtime_dependency(%q<gtk2>, [">= 0"])
+- s.add_runtime_dependency(%q<gettext>, [">= 0"])
+- s.add_runtime_dependency(%q<net-ssh>, [">= 0"])
+- else
+- s.add_dependency(%q<gtk2>, [">= 0"])
+- s.add_dependency(%q<gettext>, [">= 0"])
+- s.add_dependency(%q<net-ssh>, [">= 0"])
+- end
+- else
+- s.add_dependency(%q<gtk2>, [">= 0"])
+- s.add_dependency(%q<gettext>, [">= 0"])
+- s.add_dependency(%q<net-ssh>, [">= 0"])
+- end
+-end
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/common-install.ks virt-v2v-v0.8.1.new/p2v-image-builder/common-install.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/common-install.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/common-install.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1,54 +0,0 @@
+-lang C
+-keyboard us
+-timezone --utc UTC
+-auth --useshadow --enablemd5
+-selinux --disabled
+-firewall --disabled
+-# TODO: the sizing of the image needs to be more dynamic
+-part / --size 1024 --fstype ext2
+-services --enabled=NetworkManager --disabled=auditd
+-bootloader --timeout=30
+-rootpw --iscrypted $1$tQiZwocX$ghhurQEm56p/HqgN.XEtk1
+-
+-# add missing scsi modules to initramfs
+-device 3w-9xxx
+-device 3w-sas
+-device 3w-xxxx
+-device a100u2w
+-device aacraid
+-device aic79xx
+-device aic94xx
+-device arcmsr
+-device atp870u
+-device be2iscsi
+-device bfa
+-device BusLogic
+-device cxgb3i
+-device dc395x
+-device fnic
+-device gdth
+-device hpsa
+-device hptiop
+-device imm
+-device initio
+-device ips
+-device libosd
+-device libsas
+-device libsrp
+-device lpfc
+-device megaraid
+-device megaraid_mbox
+-device megaraid_mm
+-device megaraid_sas
+-device mpt2sas
+-device mvsas
+-device osd
+-device osst
+-device pm8001
+-device pmcraid
+-device qla1280
+-device qla2xxx
+-device qla4xxx
+-device qlogicfas408
+-device stex
+-device tmscsim
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/common-manifest-post.ks virt-v2v-v0.8.1.new/p2v-image-builder/common-manifest-post.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/common-manifest-post.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/common-manifest-post.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1,36 +0,0 @@
+-%post
+-echo -n "Creating manifest"
+-# Create post-image processing manifests
+-rpm -qa --qf '%{name}-%{version}-%{release}.%{arch} (%{SIGGPG:pgpsig})\n' | \
+- sort > /manifest-rpm.txt
+-rpm -qa --qf '%{sourcerpm}\n' | sort -u > /manifest-srpm.txt
+-# collect all included licenses rhbz#601927
+-rpm -qa --qf '%{license}\n' | sort -u > /manifest-license.txt
+-# dependencies
+-rpm -qa | xargs -n1 rpm -e --test 2> /manifest-deps.txt
+-echo -n "."
+-find / -xdev -print -exec rpm -qf {} \; > /manifest-owns.txt
+-rpm -qa --qf '%{NAME}\t%{VERSION}\t%{RELEASE}\t%{BUILDTIME}\n' | \
+- sort > /rpm-qa.txt
+-echo -n "."
+-
+-du -akx --exclude=/var/cache/yum / > /manifest-file.txt
+-du -x --exclude=/var/cache/yum / > /manifest-dir.txt
+-echo -n "."
+-bzip2 /manifest-deps.txt /manifest-owns.txt /manifest-file.txt /manifest-dir.txt
+-echo -n "."
+-
+-%end
+-
+-%post --nochroot
+-# Move manifests to ISO
+-mv $INSTALL_ROOT/manifest-* $LIVE_ROOT/isolinux
+-echo "done"
+-
+-# only works on x86, x86_64
+-if [ "$(uname -i)" = "i386" -o "$(uname -i)" = "x86_64" ]; then
+- if [ ! -d $LIVE_ROOT/LiveOS ]; then mkdir -p $LIVE_ROOT/LiveOS ; fi
+- cp /usr/bin/livecd-iso-to-disk $LIVE_ROOT/LiveOS
+- cp /usr/bin/livecd-iso-to-pxeboot $LIVE_ROOT/LiveOS
+-fi
+-%end
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/common-minimizer.ks virt-v2v-v0.8.1.new/p2v-image-builder/common-minimizer.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/common-minimizer.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/common-minimizer.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1,239 +0,0 @@
+-# This file is only relatively lightly modified from the version copied from
+-# oVirt, and certainly contains much which is irrelevant to this image. I have,
+-# however, removed some obviously extraneous entries and added a few additional
+-# entries.
+-#
+-# Matthew Booth <mbooth at redhat.com> - 18/4/2011
+-
+-%post --nochroot --interpreter image-minimizer
+-# lokkit is just an install-time dependency; we can remove
+-# it afterwards, which we do here
+-droprpm system-config-*
+-droprpm libsemanage-python
+-droprpm python-libs
+-droprpm python
+-
+-droprpm mkinitrd
+-droprpm isomd5sum
+-droprpm dmraid
+-droprpm checkpolicy
+-droprpm make
+-droprpm policycoreutils-python
+-droprpm setools-libs-python
+-droprpm setools-libs
+-
+-droprpm gamin
+-droprpm pm-utils
+-droprpm kbd
+-droprpm usermode
+-droprpm vbetool
+-droprpm ConsoleKit
+-droprpm hdparm
+-droprpm efibootmgr
+-droprpm linux-atm-libs
+-droprpm mtools
+-droprpm syslinux
+-droprpm wireless-tools
+-droprpm radeontool
+-droprpm libicu
+-droprpm gnupg2
+-droprpm fedora-release-notes
+-droprpm fedora-logos
+-
+-# cronie pulls in exim (sendmail) which pulls in all kinds of perl deps
+-droprpm exim
+-droprpm perl*
+-droprpm postfix
+-droprpm mysql*
+-
+-droprpm sysklogd
+-
+-# unneeded rhn deps
+-droprpm yum*
+-
+-# pam complains when this is missing
+-keeprpm ConsoleKit-libs
+-
+-# kernel modules minimization
+-
+-# filesystems
+-drop /lib/modules/*/kernel/fs
+-keep /lib/modules/*/kernel/fs/ext*
+-keep /lib/modules/*/kernel/fs/jbd*
+-keep /lib/modules/*/kernel/fs/btrfs
+-keep /lib/modules/*/kernel/fs/fat
+-keep /lib/modules/*/kernel/fs/nfs
+-keep /lib/modules/*/kernel/fs/nfs_common
+-keep /lib/modules/*/kernel/fs/fscache
+-keep /lib/modules/*/kernel/fs/lockd
+-keep /lib/modules/*/kernel/fs/nls/nls_utf8.ko
+-# autofs4 configfs exportfs *fat *jbd mbcache.ko nls xfs
+-#*btrfs cramfs *ext2 *fscache *jbd2 *nfs squashfs
+-# cachefiles dlm *ext3 fuse jffs2 *nfs_common ubifs
+-# cifs ecryptfs *ext4 gfs2 *lockd nfsd udf
+-
+-# network
+-drop /lib/modules/*/kernel/net
+-keep /lib/modules/*/kernel/net/802*
+-keep /lib/modules/*/kernel/net/bridge
+-keep /lib/modules/*/kernel/net/core
+-keep /lib/modules/*/kernel/net/ipv*
+-keep /lib/modules/*/kernel/net/key
+-keep /lib/modules/*/kernel/net/llc
+-keep /lib/modules/*/kernel/net/netfilter
+-keep /lib/modules/*/kernel/net/rds
+-keep /lib/modules/*/kernel/net/sctp
+-keep /lib/modules/*/kernel/net/sunrpc
+-#*802 atm can ieee802154 *key *netfilter rfkill *sunrpc xfrm
+-#*8021q bluetooth *core *ipv4 *llc phonet sched wimax
+-# 9p *bridge dccp *ipv6 mac80211 *rds *sctp wireless
+-
+-drop /lib/modules/*/kernel/sound
+-
+-# drivers
+-drop /lib/modules/*/kernel/drivers
+-keep /lib/modules/*/kernel/drivers/ata
+-keep /lib/modules/*/kernel/drivers/block
+-keep /lib/modules/*/kernel/drivers/cdrom
+-keep /lib/modules/*/kernel/drivers/char
+-keep /lib/modules/*/kernel/drivers/cpufreq
+-keep /lib/modules/*/kernel/drivers/dca
+-keep /lib/modules/*/kernel/drivers/dma
+-keep /lib/modules/*/kernel/drivers/edac
+-keep /lib/modules/*/kernel/drivers/firmware
+-keep /lib/modules/*/kernel/drivers/idle
+-keep /lib/modules/*/kernel/drivers/infiniband
+-keep /lib/modules/*/kernel/drivers/md
+-keep /lib/modules/*/kernel/drivers/message
+-keep /lib/modules/*/kernel/drivers/net
+-drop /lib/modules/*/kernel/drivers/net/pcmcia
+-drop /lib/modules/*/kernel/drivers/net/wireless
+-drop /lib/modules/*/kernel/drivers/net/ppp*
+-keep /lib/modules/*/kernel/drivers/pci
+-keep /lib/modules/*/kernel/drivers/scsi
+-keep /lib/modules/*/kernel/drivers/staging/ramzswap
+-keep /lib/modules/*/kernel/drivers/uio
+-keep /lib/modules/*/kernel/drivers/usb
+-drop /lib/modules/*/kernel/drivers/usb/atm
+-drop /lib/modules/*/kernel/drivers/usb/class
+-drop /lib/modules/*/kernel/drivers/usb/image
+-drop /lib/modules/*/kernel/drivers/usb/misc
+-drop /lib/modules/*/kernel/drivers/usb/serial
+-keep /lib/modules/*/kernel/drivers/vhost
+-keep /lib/modules/*/kernel/drivers/virtio
+-
+-# acpi *cpufreq hid leds mtd ?regulator uwb
+-#*ata crypto ?hwmon *md *net* rtc *vhost
+-# atm *dca ?i2c media ?parport *scsi* video
+-# auxdisplay *dma *idle memstick *pci ?serial *virtio
+-#*block *edac ieee802154 *message pcmcia ?ssb watchdog
+-# bluetooth firewire *infiniband ?mfd platform *staging xen
+-#*cdrom *firmware input misc ?power ?uio
+-#*char* ?gpu isdn mmc ?pps *usb
+-
+-drop /usr/share/zoneinfo
+-keep /usr/share/zoneinfo/UTC
+-
+-drop /etc/alsa
+-drop /usr/share/alsa
+-drop /usr/share/awk
+-drop /usr/share/vim
+-drop /usr/share/anaconda
+-drop /usr/share/backgrounds
+-drop /usr/share/wallpapers
+-drop /usr/share/kde-settings
+-drop /usr/share/gnome-background-properties
+-drop /usr/share/dracut
+-drop /usr/share/plymouth
+-drop /usr/share/setuptool
+-drop /usr/share/hwdata/MonitorsDB
+-drop /usr/share/hwdata/oui.txt
+-drop /usr/share/hwdata/videoaliases
+-drop /usr/share/hwdata/videodrivers
+-drop /usr/share/firstboot
+-drop /usr/share/lua
+-drop /usr/share/kde4
+-drop /usr/share/pixmaps
+-drop /usr/share/icons
+-drop /usr/share/fedora-release
+-drop /usr/share/tabset
+-
+-drop /usr/share/tc
+-drop /usr/share/emacs
+-drop /usr/share/info
+-drop /usr/src
+-drop /usr/etc
+-drop /usr/games
+-drop /usr/include
+-drop /usr/local
+-drop /usr/sbin/dell*
+-keep /usr/sbin/build-locale-archive
+-drop /usr/sbin/glibc_post_upgrade.*
+-drop /usr/lib*/tc
+-drop /usr/lib*/tls
+-drop /usr/lib*/sse2
+-drop /usr/lib*/pkgconfig
+-drop /usr/lib*/nss
+-drop /usr/lib*/games
+-drop /usr/lib*/alsa-lib
+-drop /usr/lib*/krb5
+-drop /usr/lib*/hal
+-drop /usr/lib*/gio
+-
+-# syslinux
+-drop /usr/share/syslinux
+-# glibc-common locales
+-drop /usr/lib/locale
+-keep /usr/lib/locale/usr/share/locale/en_US
+-# openssh
+-drop /usr/bin/sftp
+-drop /usr/bin/slogin
+-drop /usr/bin/ssh-add
+-drop /usr/bin/ssh-agent
+-drop /usr/bin/ssh-keyscan
+-# docs
+-drop /usr/share/omf
+-drop /usr/share/gnome
+-drop /usr/share/doc
+-keep /usr/share/doc/*-firmware-*
+-drop /usr/share/locale/
+-keep /usr/share/locale/en_US
+-drop /usr/share/man
+-drop /usr/share/i18n
+-drop /boot/*
+-drop /var/lib/builder
+-
+-drop /usr/lib*/libboost*
+-keep /usr/lib*/libboost_program_options.so*
+-keep /usr/lib*/libboost_filesystem.so*
+-keep /usr/lib*/libboost_thread-mt.so*
+-keep /usr/lib*/libboost_system.so*
+-drop /usr/kerberos
+-keep /usr/kerberos/bin/kinit
+-keep /usr/kerberos/bin/klist
+-drop /lib/firmware
+-keep /lib/firmware/3com
+-keep /lib/firmware/acenic
+-keep /lib/firmware/adaptec
+-keep /lib/firmware/advansys
+-keep /lib/firmware/bnx2
+-keep /lib/firmware/cxgb3
+-keep /lib/firmware/e100
+-keep /lib/firmware/myricom
+-keep /lib/firmware/ql*
+-keep /lib/firmware/sun
+-keep /lib/firmware/tehuti
+-keep /lib/firmware/tigon
+-drop /lib/kbd/consolefonts
+-drop /etc/pki/tls
+-drop /etc/pki/java
+-drop /etc/pki/nssdb
+-drop /etc/pki/rpm-gpg
+-%end
+-
+-%post
+-echo "Removing python source files"
+-find / -name '*.py' -exec rm -f {} \;
+-find / -name '*.pyo' -exec rm -f {} \;
+-
+-%end
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/common-pkgs.ks virt-v2v-v0.8.1.new/p2v-image-builder/common-pkgs.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/common-pkgs.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/common-pkgs.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1,48 +0,0 @@
+-# Direct requirements
+-rubygem-virt-p2v
+-bitstream-vera-sans-fonts
+-xorg-x11-xinit
+-xorg-x11-drivers
+-xorg-x11-server-Xorg
+-
+-# Boot requirements
+-device-mapper
+-
+-# Required for livecd creation
+-passwd
+-rpm
+-/usr/sbin/lokkit
+-
+-# Remove unnecessary packages
+--audit-libs-python
+--ustr
+--authconfig
+--wireless-tools
+--setserial
+--prelink
+--newt-python
+--newt
+--libselinux-python
+--kbd
+--usermode
+--fedora-release
+--fedora-release-notes
+--dmraid
+--gzip
+--less
+--which
+--parted
+--tar
+--libuser
+--mtools
+--cpio
+--yum
+--numactl # Pulls in perl dependency
+--perl
+-
+-# qlogic firmware
+-ql2100-firmware
+-ql2200-firmware
+-ql23xx-firmware
+-ql2400-firmware
+-ql2500-firmware
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/common-post.ks virt-v2v-v0.8.1.new/p2v-image-builder/common-post.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/common-post.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/common-post.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1,43 +0,0 @@
+-# -*-Shell-script-*-
+-echo "Starting Kickstart Post"
+-PATH=/sbin:/usr/sbin:/bin:/usr/bin
+-export PATH
+-
+-# cleanup rpmdb to allow non-matching host and chroot RPM versions
+-rm -f /var/lib/rpm/__db*
+-
+-echo "Creating shadow files"
+-# because we aren't installing authconfig, we aren't setting up shadow
+-# and gshadow properly. Do it by hand here
+-pwconv
+-grpconv
+-
+-echo "Forcing C locale"
+-# force logins (via ssh, etc) to use C locale, since we remove locales
+-cat >> /etc/profile << \EOF
+-# force our locale to C since we don't have locale stuff'
+-export LC_ALL=C LANG=C
+-EOF
+-
+-# remove errors from /sbin/dhclient-script
+-DHSCRIPT=/sbin/dhclient-script
+-sed -i 's/mv /cp -p /g' $DHSCRIPT
+-sed -i '/rm -f.*${interface}/d' $DHSCRIPT
+-sed -i '/rm -f \/etc\/localtime/d' $DHSCRIPT
+-sed -i '/rm -f \/etc\/ntp.conf/d' $DHSCRIPT
+-sed -i '/rm -f \/etc\/yp.conf/d' $DHSCRIPT
+-
+-# Lock root account
+-#passwd -l root
+-
+-#strip out all unncesssary locales
+-localedef --list-archive | grep -v -i -E 'en_US.utf8' |xargs localedef --delete-from-archive
+-mv /usr/lib/locale/locale-archive /usr/lib/locale/locale-archive.tmpl
+-/usr/sbin/build-locale-archive
+-
+-# Run virt-p2v
+-cat >> /etc/rc.local <<EOF
+-export HOME=/root # rubygem Net::SSH needs this
+-/usr/bin/xinit /usr/bin/virt-p2v > /root/virt-p2v.log 2>&1
+-poweroff
+-EOF
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/common-post-nochroot.ks virt-v2v-v0.8.1.new/p2v-image-builder/common-post-nochroot.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/common-post-nochroot.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/common-post-nochroot.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1,60 +0,0 @@
+-%include version.ks
+-
+-PRODUCT='Virt P2V'
+-PRODUCT_SHORT='virt-p2v'
+-PACKAGE='virt-p2v'
+-RELEASE=${RELEASE:-devel.`date +%Y%m%d%H%M%S`}
+-
+-echo "Customizing boot menu"
+-sed -i -e '
+-# Put product information at the top of the file
+-1 {
+- i '"say $PRODUCT $VERSION ($RELEASE)"'
+- i '"menu title $PRODUCT_SHORT $VERSION ($RELEASE)"'
+-}
+-
+-# Remove any existing menu title
+-/^menu title .*/d
+-
+-# Remove quiet bootparam
+-#s/ quiet//
+-
+-# Disable selinux entirely. Required, as we dont install an SELinux policy.
+-/^\s*append\s/ s/\s*$/ selinux=0/
+-
+-# Remove Verify and Boot option
+-/label check0/{N;N;N;d;}
+-
+-# Set the default timeout to 15 seconds
+-s/^timeout .*/timeout 15/
+-' $LIVE_ROOT/isolinux/isolinux.cfg
+-
+-# TODO: Replace the splash screen with something P2V appropriate
+-#cp $INSTALL_ROOT//syslinux-vesa-splash.jpg $LIVE_ROOT/isolinux/splash.jpg
+-
+-# store image version info in the ISO
+-cat > $LIVE_ROOT/isolinux/version <<EOF
+-PRODUCT='$PRODUCT'
+-PRODUCT_SHORT='${PRODUCT_SHORT}'
+-PRODUCT_CODE=$PRODUCT_CODE
+-RECIPE_SHA256=$RECIPE_SHA256
+-RECIPE_RPM=$RECIPE_RPM
+-PACKAGE=$PACKAGE
+-VERSION=$VERSION
+-RELEASE=$RELEASE
+-EOF
+-
+-# overwrite user visible banners with the image versioning info
+-cat > $INSTALL_ROOT/etc/$PACKAGE-release <<EOF
+-$PRODUCT release $VERSION ($RELEASE)
+-EOF
+-ln -snf $PACKAGE-release $INSTALL_ROOT/etc/redhat-release
+-ln -snf $PACKAGE-release $INSTALL_ROOT/etc/system-release
+-cp $INSTALL_ROOT/etc/$PACKAGE-release $INSTALL_ROOT/etc/issue
+-echo "Kernel \r on an \m (\l)" >> $INSTALL_ROOT/etc/issue
+-cp $INSTALL_ROOT/etc/issue $INSTALL_ROOT/etc/issue.net
+-
+-# replace initramfs if regenerated
+-if [ -f "$INSTALL_ROOT/initrd0.img" ]; then
+- mv -v "$INSTALL_ROOT/initrd0.img" "$LIVE_ROOT/isolinux/initrd0.img"
+-fi
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/Makefile virt-v2v-v0.8.1.new/p2v-image-builder/Makefile
+--- virt-v2v-v0.8.1/p2v-image-builder/Makefile 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/Makefile 1970-01-01 01:00:00.000000000 +0100
+@@ -1,2 +0,0 @@
+-version.ks: ../Build
+- echo VERSION=`../Build version` > version.ks
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/version.ks virt-v2v-v0.8.1.new/p2v-image-builder/version.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/version.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/version.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1 +0,0 @@
+-VERSION=0.8.1
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/virt-p2v-image-builder virt-v2v-v0.8.1.new/p2v-image-builder/virt-p2v-image-builder
+--- virt-v2v-v0.8.1/p2v-image-builder/virt-p2v-image-builder 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/virt-p2v-image-builder 1970-01-01 01:00:00.000000000 +0100
+@@ -1,188 +0,0 @@
+-#!/bin/bash
+-
+-# Copyright (C) 2010-2011, Red Hat, Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; version 2 of the License.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+-# MA 02110-1301, USA. A copy of the GNU General Public License is
+-# also available at http://www.gnu.org/copyleft/gpl.html.
+-
+-# Requires: sudo livecd-creator, sudo setenforce, ksflatten
+-
+-# Based on oVirt's node-creator
+-
+-# Current fedora data
+-cur_rawhide=16
+-cur_devel=15
+-
+-me=$(basename "$0")
+-warn() { printf '%s: %s\n' "$me" "$*" >&2; }
+-die() { warn "$*"; exit 1; }
+-usage() {
+-cat <<EOF
+-usage: $me <options>
+-
+-Build a virt-p2v bootable image.
+-
+-OPTIONS:
+- -a Additional yum repository. Can be specified multiple times.
+- -c Yum cache directory.
+- -d Directory containing virt-p2v-image.ks.
+- -f Specific Fedora mirror to use if building a Fedora image.
+- -l Boot image label.
+- -r Primary yum repository.
+- -u Updates yum repository.
+- -h Show this message.
+-EOF
+-}
+-
+-onlyonce() {
+- warn "-$1 may only be specified once"
+- usage
+- exit 1
+-}
+-
+-while getopts "a:d:f:hl:r:u:w:" OPTION
+-do
+- case $OPTION in
+- a)
+- n_elems=${#extra_repos[*]}
+- extra_repos[$n_elems]="$OPTARG"
+- ;;
+- c)
+- [ -n "$cachedir" ] && onlyonce $OPTION
+- cachedir="$OPTARG"
+- ;;
+- d)
+- [ -n "$datadir" ] && onlyonce $OPTION
+- datadir="$OPTARG"
+- ;;
+- f)
+- [ -n "$fedora_url" ] && onlyonce $OPTION
+- fedora_url="$OPTARG"
+- ;;
+- l)
+- [ -n "$label" ] && onlyonce $OPTION
+- label="$OPTARG"
+- ;;
+- r)
+- [ -n "$repo" ] && onlyonce $OPTION
+- repo="$OPTARG"
+- ;;
+- u)
+- [ -n "$updates" ] && onlyonce $OPTION
+- updates="$OPTARG"
+- ;;
+- h)
+- usage
+- exit 0
+- ;;
+- ?)
+- usage
+- exit 1
+- ;;
+- esac
+-done
+-
+-# Split out here for simple editing with sed during installation
+-DEFAULT_DATADIR=.
+-
+-# Option defaults
+-datadir="${datadir:-$DEFAULT_DATADIR}"
+-cachedir="${cachedir:-/var/tmp/p2v-image-builder.$USER}"
+-label="${label:-Virt-P2V}"
+-
+-arch=$(rpm --eval '%{_arch}')
+-kstmp=$(mktemp --tmpdir p2v-image-builder.XXXXXXXX)
+-
+-if pgrep -xl nscd; then
+- die "Please stop nscd first"
+-fi
+-
+-rm -f "$kstmp"
+-# combine recipe includes
+-ksflatten --config "$datadir/virt-p2v-image.ks" --output "$kstmp"
+-# XXX broken ksflatten leaves %include
+-sed -i 's/^%include /#&/' "$kstmp"
+-
+-if [ -z "$repo" ]; then
+- # Set defaults for Fedora if this is a fedora system
+- fedora=$(rpm --eval '%{fedora}' |grep [0-9])
+-
+- mirrorlist="http://mirrors.fedoraproject.org/mirrorlist"
+-
+- case "$fedora" in
+- $curr_rawhide)
+- if [ -z "$fedora_url" ]; then
+- repo="--mirrorlist=$mirrorlist?repo=rawhide&arch=$arch"
+- else
+- repo="--baseurl=$fedora_url/development/rawhide/$arch/os"
+- fi
+- ;;
+- $cur_devel)
+- if [ -z "$fedora_url" ]; then
+- repo="--mirrorlist=$mirrorlist?repo=fedora-$fedora&arch=$arch"
+- else
+- repo="--baseurl=$fedora_url/development/$fedora/$arch/os"
+- fi
+- ;;
+- ?*)
+- if [ -z "$fedora_url" ]; then
+- repo="--mirrorlist=$mirrorlist?repo=fedora-$fedora&arch=$arch"
+- updates="--mirrorlist=$mirrorlist?repo=updates-released-f${fedora}&arch=$arch"
+- else
+- repo="--baseurl=$fedora_url/releases/$fedora/Everything/$arch/os"
+- updates="--baseurl=$fedora_url/updates/$fedora/$arch"
+- fi
+- esac
+-else
+- repo="--baseurl=$repo"
+- [ -n "$updates" ] && updates="--baseurl=$updates"
+-fi
+-
+-if [ -n "$repo" ]; then
+- echo "repo --name=base $repo" >> "$kstmp"
+-else
+- die "No repository specified, and no default available."
+-fi
+-if [ -n "$updates" ]; then
+- echo "repo --name=updates $updates" >> "$kstmp"
+-fi
+-i=0
+-for extra in "${extra_repos[@]}"; do
+- ((i++))
+- [ -d "$extra" ] && extra="file://$extra"
+- echo "repo --name=extra$i --baseurl=$extra" >> "$kstmp"
+-done
+-
+-selinux_enforcing=$(/usr/sbin/getenforce)
+-case "$selinux_enforcing" in
+- Enforcing) sudo /usr/sbin/setenforce Permissive ;;
+- Permissive) ;;
+- *) if grep -q '^selinux --disabled' "$kstmp";
+- then
+- warn "WARNING: SELinux disabled in kickstart"
+- else
+- die "ERROR: SELinux enabled in kickstart, \
+- but disabled on the build machine"
+- fi ;;
+-esac
+-
+-mkdir -p $cachedir
+-sudo livecd-creator -c "$kstmp" -f "$label" --cache="$cachedir"
+-
+-# Clean up
+-rm -f $kstmp
+-if [ "$selinux_enforcing" = Enforcing ]; then
+- sudo /usr/sbin/setenforce Enforcing
+-fi
+diff -ruN virt-v2v-v0.8.1/p2v-image-builder/virt-p2v-image.ks virt-v2v-v0.8.1.new/p2v-image-builder/virt-p2v-image.ks
+--- virt-v2v-v0.8.1/p2v-image-builder/virt-p2v-image.ks 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-image-builder/virt-p2v-image.ks 1970-01-01 01:00:00.000000000 +0100
+@@ -1,19 +0,0 @@
+-# virt-p2v Node image recipe
+-
+-%include common-install.ks
+-
+-%packages --excludedocs --nobase
+-%include common-pkgs.ks
+-%end
+-
+-%post
+-%include common-post.ks
+-%end
+-
+-%include common-minimizer.ks
+-
+-%post --nochroot
+-%include common-post-nochroot.ks
+-%end
+-
+-%include common-manifest-post.ks
+diff -ruN virt-v2v-v0.8.1/p2v-server/run-p2v-locally virt-v2v-v0.8.1.new/p2v-server/run-p2v-locally
+--- virt-v2v-v0.8.1/p2v-server/run-p2v-locally 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-server/run-p2v-locally 1970-01-01 01:00:00.000000000 +0100
+@@ -1,52 +0,0 @@
+-#!/bin/sh
+-# virt-p2v
+-# Copyright (C) 2010 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-# This script sets up the environment so you can run virt-v2v in place
+-# without needing to do 'make install' first.
+-#
+-# Use it like this:
+-# ./run-p2v-locally
+-#
+-# It requires the environment variable VIRTV2V_ROOT to be set. If using
+-# libguestfs from source, LIBGUESTFS_ROOT must also be set.
+-
+-if [ -z "$VIRTV2V_ROOT" ]; then
+- echo "VIRTV2V_ROOT must be set"
+- exit 1
+-fi
+-
+-if [ -z "$PERL5LIB" ]; then
+- PERL5LIB="$VIRTV2V_ROOT/blib/lib"
+-else
+- PERL5LIB="$VIRTV2V_ROOT/blib/lib:$PERL5LIB"
+-fi
+-
+-if [ ! -z "$LIBGUESTFS_ROOT" ]; then
+- if [ -z "$LD_LIBRARY_PATH" ]; then
+- LD_LIBRARY_PATH="$LIBGUESTFS_ROOT/src/.libs"
+- else
+- LD_LIBRARY_PATH="$LIBGUESTFS_ROOT/src/.libs:$LD_LIBRARY_PATH"
+- fi
+-
+- LIBGUESTFS_PATH="$LIBGUESTFS_ROOT/appliance"
+- PERL5LIB="$LIBGUESTFS_ROOT/perl/blib/lib:$LIBGUESTFS_ROOT/perl/blib/arch:$PERL5LIB"
+-fi
+-
+-export PERL5LIB LD_LIBRARY_PATH LIBGUESTFS_PATH
+-
+-exec perl "$VIRTV2V_ROOT/p2v-server/virt-p2v-server.pl" "$@"
+diff -ruN virt-v2v-v0.8.1/p2v-server/virt-p2v-server.pl virt-v2v-v0.8.1.new/p2v-server/virt-p2v-server.pl
+--- virt-v2v-v0.8.1/p2v-server/virt-p2v-server.pl 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/p2v-server/virt-p2v-server.pl 1970-01-01 01:00:00.000000000 +0100
+@@ -1,505 +0,0 @@
+-#!/usr/bin/perl
+-# virt-p2v-server
+-# Copyright (C) 2011 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-use warnings;
+-use strict;
+-
+-use IO::Handle;
+-use YAML::Any;
+-
+-use Locale::TextDomain 'virt-v2v';
+-
+-use Sys::Guestfs;
+-
+-use Sys::VirtConvert;
+-use Sys::VirtConvert::Config;
+-use Sys::VirtConvert::Converter;
+-use Sys::VirtConvert::Connection::LibVirtTarget;
+-use Sys::VirtConvert::Connection::RHEVTarget;
+-use Sys::VirtConvert::GuestfsHandle;
+-use Sys::VirtConvert::Util qw(:DEFAULT logmsg_init logmsg_level);
+-
+-=encoding utf8
+-
+-=head1 NAME
+-
+-virt-p2v-server - Receive data from virt-p2v
+-
+-=head1 DESCRIPTION
+-
+-virt-p2v-server is invoked over SSH by virt-p2v. It is not intended to be run
+-manually.
+-
+-=cut
+-
+-# SIGPIPE will cause an untidy exit of the perl process, without calling
+-# destructors. We don't rely on it anywhere, as we check for errors when reading
+-# from or writing to a pipe.
+-$SIG{'PIPE'} = 'IGNORE';
+-
+-# The protocol version we support
+-use constant VERSION => 0;
+-
+-# Message types
+-use constant MSG_VERSION => 'VERSION';
+-use constant MSG_LANG => 'LANG';
+-use constant MSG_METADATA => 'METADATA';
+-use constant MSG_PATH => 'PATH';
+-use constant MSG_CONVERT => 'CONVERT';
+-use constant MSG_LIST_PROFILES => 'LIST_PROFILES';
+-use constant MSG_SET_PROFILE => 'SET_PROFILE';
+-use constant MSG_CONTAINER => 'CONTAINER';
+-use constant MSG_DATA => 'DATA';
+-
+-# Container types
+-use constant CONT_RAW => 'RAW';
+-
+-# Global state
+-my $config;
+-my $meta;
+-my $target;
+-
+-# Initialize logging
+-logmsg_init('syslog');
+-#logmsg_level(DEBUG);
+-
+-logmsg NOTICE, __x("{program} started.", program => 'p2v-server');
+-
+-# Wrap everything in a big eval to catch any die(). N.B. $SIG{__DIE__} is no
+-# good for this, as it catches every die(), even those inside an eval
+-eval {
+- # Set the umask to a reasonable default
+- umask(0022);
+-
+- # Don't buffer output
+- # While perl will use line buffering when STDOUT is connected to a tty, when
+- # not connected to a tty, for example when invoked directly over ssh, it
+- # will use a regular, large output buffer. This results in messages being
+- # held in the buffer indefinitely.
+- STDOUT->autoflush(1);
+-
+- # Read the config file
+- eval {
+- $config = Sys::VirtConvert::Config->new('/etc/virt-v2v.conf');
+- };
+- v2vdie $@ if $@;
+-
+- my $msg;
+- while ($msg = p2v_receive()) {
+- my $type = $msg->{type};
+-
+- # VERSION n
+- if ($type eq MSG_VERSION) {
+- my $version = $msg->{args}[0];
+- if ($version <= VERSION) {
+- p2v_return_ok();
+- }
+-
+- else {
+- err_and_die(__x('This version of virt-p2v-server does not '.
+- 'support protocol version {version}.',
+- version => $version));
+- }
+- }
+-
+- # LANG lang
+- elsif ($type eq MSG_LANG) {
+- $ENV{LANG} = $msg->{args}[0];
+- p2v_return_ok();
+- }
+-
+- # METADATA length
+- # length bytes of YAML
+- elsif ($type eq MSG_METADATA) {
+- my $yaml = p2v_read($msg->{args}[0]);
+- eval { $meta = Load($yaml); };
+- err_and_die('Error parsing metadata: '.$@) if $@;
+-
+- p2v_return_ok();
+- }
+-
+- # PATH length path
+- # N.B. path could theoretically include spaces
+- elsif ($type eq MSG_PATH) {
+- my $length = $msg->{args}[0];
+-
+- my $path = join(' ', @{$msg->{args}}[1..$#{$msg->{args}}]);
+- receive_path($path, $length);
+- }
+-
+- # CONVERT
+- elsif ($type eq MSG_CONVERT) {
+- convert();
+- }
+-
+- # LIST_PROFILES
+- elsif ($type eq MSG_LIST_PROFILES) {
+- p2v_return_list($config->list_profiles());
+- }
+-
+- # SET_PROFILE profile
+- elsif ($type eq MSG_SET_PROFILE) {
+- set_profile($msg->{args}[0]);
+- }
+-
+- else {
+- unexpected_msg($type);
+- }
+- }
+-};
+-logmsg FATAL, $@ if $@;
+-
+-exit(0);
+-
+-# Receive an image file
+-sub receive_path
+-{
+- my ($path, $length) = @_;
+-
+- err_and_die('PATH without prior SET_PROFILE command')
+- unless defined($target);
+- err_and_die('PATH without prior METADATA command')
+- unless defined($meta);
+-
+- my ($disk) = grep { $_->{path} eq $path } @{$meta->{disks}};
+- err_and_die("$path not found in metadata") unless defined($disk);
+-
+- # Construct a volume name based on the path and hostname
+- my $name = $meta->{name}.'-'.$disk->{device};
+- $name =~ s,/,_,g; # e.g. cciss devices have a directory structure
+-
+- my $sopts = $config->get_storage_opts();
+-
+- my $convert = 0;
+- my $format;
+- my $sparse;
+-
+- # Default to raw. Conversion required for anything else.
+- if (!exists($sopts->{format}) || $sopts->{format} eq 'raw') {
+- $format = 'raw';
+- } else {
+- $format = $sopts->{format};
+- $convert = 1;
+- }
+-
+- # Default to non-sparse
+- my $allocation = $sopts->{allocation};
+- if (!defined($allocation) || $allocation eq 'preallocated') {
+- $sparse = 0;
+- } elsif ($allocation eq 'sparse') {
+- $sparse = 1;
+- } else {
+- err_and_die(__x('Invalid allocation policy {policy} in profile.',
+- policy => $allocation));
+- }
+-
+- # Create the target volume
+- my $vol;
+- eval {
+- $vol = $target->create_volume(
+- $name,
+- $format,
+- $length,
+- $sparse
+- );
+- };
+- err_and_die($@) if $@;
+- p2v_return_ok();
+-
+- # Receive an initial container
+- my $msg = p2v_receive();
+- unexpected_msg($msg->{type}) unless $msg->{type} eq MSG_CONTAINER;
+-
+- # We only support RAW container
+- my $ctype = $msg->{args}[0];
+- err_and_die("Received unknown container type: $ctype")
+- unless $ctype eq CONT_RAW;
+- p2v_return_ok();
+-
+- # Update the disk entry with the new volume details
+- $disk->{local_path} = $vol->get_local_path();
+- $disk->{path} = $vol->get_path();
+- $disk->{is_block} = $vol->is_block();
+-
+- my $writer = $vol->get_write_stream($convert);
+-
+- # Receive volume data in chunks
+- my $received = 0;
+- while ($received < $length) {
+- my $data = p2v_receive();
+-
+- unexpected_msg($data->command) unless $data->{type} eq MSG_DATA;
+-
+- # Read the data message in chunks of up to 4M
+- my $remaining = $data->{args}[0];
+- while ($remaining > 0) {
+- my $chunk = $remaining > 4*1024*1024 ? 4*1024*1024 : $remaining;
+- my $buf = p2v_read($chunk);
+-
+- $received += $chunk;
+- $remaining -= $chunk;
+-
+- eval { $writer->write($buf); };
+- err_and_die($@) if $@;
+- }
+-
+- p2v_return_ok();
+- }
+-}
+-
+-# Use the specified profile
+-sub set_profile
+-{
+- my ($profile) = @_;
+-
+- # Check the profile is in our list
+- my $found = 0;
+- for my $i ($config->list_profiles()) {
+- if ($i eq $profile) {
+- $found = 1;
+- last;
+- }
+- }
+- err_and_die(__x('Invalid profile: {profile}', profile => $profile))
+- unless ($found);
+-
+- $config->use_profile($profile);
+-
+- my $storage = $config->get_storage();
+- my $method = $config->get_method();
+- if ($method eq 'libvirt') {
+- $target = new Sys::VirtConvert::Connection::LibVirtTarget
+- ('qemu:///system', $storage);
+- } elsif ($method eq 'rhev') {
+- $target = new Sys::VirtConvert::Connection::RHEVTarget($storage);
+- } else {
+- err_and_die(__x('Profile {profile} specifies invalid method {method}.',
+- profile => $profile, method => $method));
+- }
+-
+- p2v_return_ok();
+-}
+-
+-sub convert
+-{
+- err_and_die('CONVERT without prior SET_PROFILE command')
+- unless (defined($target));
+-
+- err_and_die('CONVERT without prior METADATA command')
+- unless defined($meta);
+-
+- my @localpaths = map { $_->{local_path} } @{$meta->{disks}};
+-
+- my $g;
+- eval {
+- my $transferiso = $config->get_transfer_iso();
+-
+- $g = new Sys::VirtConvert::GuestfsHandle(
+- \@localpaths,
+- $transferiso,
+- $target->isa('Sys::VirtConvert::Connection::RHEVTarget')
+- );
+-
+- my $transferdev;
+- if (defined($transferiso)) {
+- my @devices = $g->list_devices();
+- $transferdev = pop(@devices);
+- }
+-
+- my $root = inspect_guest($g, $transferdev);
+- my $guestcaps =
+- Sys::VirtConvert::Converter->convert($g, $config, $root, $meta);
+- $target->create_guest($g, $root, $meta, $config, $guestcaps,
+- $meta->{name});
+-
+- if($guestcaps->{block} eq 'virtio' && $guestcaps->{net} eq 'virtio') {
+- logmsg NOTICE, __x('{name} configured with virtio drivers.',
+- name => $meta->{name});
+- } elsif ($guestcaps->{block} eq 'virtio') {
+- logmsg NOTICE, __x('{name} configured with virtio storage only.',
+- name => $meta->{name});
+- } elsif ($guestcaps->{net} eq 'virtio') {
+- logmsg NOTICE, __x('{name} configured with virtio networking only.',
+- name => $meta->{name});
+- } else {
+- logmsg NOTICE, __x('{name} configured without virtio drivers.',
+- name => $meta->{name});
+- }
+- };
+-
+- # If any of the above commands result in failure, we need to ensure that
+- # the guestfs qemu process is cleaned up before further cleanup. Failure to
+- # do this can result in failure to umount RHEV export's temporary mount
+- # point.
+- if ($@) {
+- my $err = $@;
+- $g->close();
+-
+- # We trust the error was already logged
+- p2v_return_err($err);
+- die($@);
+- }
+-
+- p2v_return_ok();
+-}
+-
+-sub unexpected_msg
+-{
+- err_and_die('Received unexpected command: '.shift);
+-}
+-
+-sub err_and_die
+-{
+- my $err = shift;
+- p2v_return_err($err);
+- v2vdie $err;
+-}
+-
+-END {
+- my $err = $?;
+-
+- logmsg NOTICE, __x("{program} exited.", program => 'p2v-server');
+-
+- # die() sets $? to 255, which is untidy.
+- $? = $err == 255 ? 1 : $err;
+-}
+-
+-# Perform guest inspection using the libguestfs core inspection API.
+-# Returns the root device of the os to be converted.
+-sub inspect_guest
+-{
+- my $g = shift;
+- my $transferdev = shift;
+-
+- # Get list of roots, sorted
+- my @roots = $g->inspect_os();
+-
+- # Filter out the transfer device from the results of inspect_os
+- # There's a libguestfs bug (fixed upstream) which meant the transfer ISO
+- # could be erroneously detected as an unknown Windows OS. As we know what it
+- # is, we can filter out the transfer device here. Even when the fix is
+- # released this is reasonable belt & braces.
+- @roots = grep(!/^\Q$transferdev\E$/, @roots);
+-
+- @roots = sort @roots;
+-
+- # Only work on single-root operating systems.
+- v2vdie __('No root device found in this operating system image.')
+- if @roots == 0;
+-
+- v2vdie __('Multiboot operating systems are not supported.')
+- if @roots > 1;
+-
+- return $roots[0];
+-}
+-
+-sub p2v_receive
+-{
+- my $in = <>;
+- v2vdie __('Client closed connection unexpectedly') unless defined($in);
+-
+- # Messages consist of the message type followed by 0 or more arguments,
+- # terminated by a newline
+- chomp($in);
+- $in =~ /^([A-Z_]+)( .+)?$/ or err_and_die("Received invalid message: $in");
+-
+- my %msg;
+- $msg{type} = $1;
+- if (defined($2)) {
+- my @args = split(' ', $2);
+- $msg{args} = \@args;
+- } else {
+- $msg{args} = [];
+- }
+-
+- logmsg DEBUG, __x('Received: {command} {args}',
+- command => $msg{type},
+- args => join(' ', @{$msg{args}}));
+-
+- return \%msg;
+-}
+-
+-sub p2v_read
+-{
+- my ($length) = @_;
+-
+- my $buf;
+- my $total = 0;
+-
+- while($total < $length) {
+- my $in = read(STDIN, $buf, $length, $total)
+- or err_and_die(__x('Error receiving data: {error}', error => $@));
+- logmsg DEBUG, "Read $in bytes";
+- $total += $in;
+- }
+-
+- return $buf;
+-}
+-
+-sub p2v_return_ok
+-{
+- my $msg = "OK";
+- logmsg DEBUG, __x('Sent: {msg}', msg => $msg);
+- print $msg,"\n";
+-}
+-
+-sub p2v_return_list
+-{
+- my @values = @_;
+-
+- my $msg = 'LIST '.scalar(@values);
+- foreach my $value (@values) {
+- $msg .= "\n$value";
+- }
+- logmsg DEBUG, __x('Sent: {msg}', msg => $msg);
+- print $msg,"\n";
+-}
+-
+-sub p2v_return_err
+-{
+- my $msg = 'ERROR '.shift;
+- logmsg DEBUG, __x('Sent: {msg}', msg => $msg);
+- print $msg,"\n";
+-}
+-
+-=head1 SEE ALSO
+-
+-L<virt-v2v(1)>,
+-L<http://libguestfs.org/>.
+-
+-=head1 AUTHOR
+-
+-Matthew Booth <mbooth at redhat.com>
+-
+-=head1 COPYRIGHT
+-
+-Copyright (C) 2011 Red Hat Inc.
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU General Public License as published by
+-the Free Software Foundation; either version 2 of the License, or
+-(at your option) any later version.
+-
+-This program is distributed in the hope that it will be useful,
+-but WITHOUT ANY WARRANTY; without even the implied warranty of
+-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-GNU General Public License for more details.
+-
+-You should have received a copy of the GNU General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+diff -ruN virt-v2v-v0.8.1/virt-v2v.spec virt-v2v-v0.8.1.new/virt-v2v.spec
+--- virt-v2v-v0.8.1/virt-v2v.spec 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/virt-v2v.spec 2011-05-11 17:20:21.000000000 +0100
+@@ -55,7 +55,6 @@
+
+ # virt-p2v build requirements
+ BuildRequires: rubygem(rake)
+-BuildRequires: rubygem(echoe)
+
+ Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
+
+@@ -141,7 +140,7 @@
+ %{__perl} Build.PL
+ ./Build
+
+-pushd p2v-client
++pushd p2v/client
+ rake gem
+ popd
+
+@@ -174,7 +173,7 @@
+ mkdir -p %{buildroot}/%{gemdir}
+
+ gem install --local --install-dir %{buildroot}%{gemdir} \
+- --force --rdoc p2v-client/pkg/%{gemname}-%{version}.gem
++ --force --rdoc p2v/client/pkg/%{gemname}-%{version}.gem
+ mv %{buildroot}%{gemdir}/bin/* %{buildroot}/%{_bindir}
+ find %{buildroot}%{geminstdir}/bin -type f | xargs chmod a+x
+ cp COPYING %{buildroot}/%{geminstdir}
+@@ -183,8 +182,8 @@
+ %global builderdir %{_datadir}/virt-p2v-image-builder
+ builder=%{buildroot}/%{_bindir}/virt-p2v-image-builder
+ mkdir -p %{buildroot}%{builderdir}
+-cp p2v-image-builder/*.ks %{buildroot}%{builderdir}
+-cp p2v-image-builder/virt-p2v-image-builder $builder
++cp p2v/image-builder/*.ks %{buildroot}%{builderdir}
++cp p2v/image-builder/virt-p2v-image-builder $builder
+
+ # Set the default data directory
+ sed -i -e 's,^DEFAULT_DATADIR=.*,DEFAULT_DATADIR=%{builderdir},' $builder
+@@ -193,7 +192,7 @@
+ %check
+ ./Build test
+
+-pushd p2v-client
++pushd p2v/client
+ # No tests yet
+ #rake test
+ popd
+diff -ruN virt-v2v-v0.8.1/virt-v2v.spec.PL virt-v2v-v0.8.1.new/virt-v2v.spec.PL
+--- virt-v2v-v0.8.1/virt-v2v.spec.PL 2011-04-26 20:58:33.000000000 +0100
++++ virt-v2v-v0.8.1.new/virt-v2v.spec.PL 2011-05-11 17:20:21.000000000 +0100
+@@ -165,7 +165,7 @@
+ %{__perl} Build.PL
+ ./Build
+
+-pushd p2v-client
++pushd p2v/client
+ rake gem
+ popd
+
+@@ -198,7 +198,7 @@
+ mkdir -p %{buildroot}/%{gemdir}
+
+ gem install --local --install-dir %{buildroot}%{gemdir} \
+- --force --rdoc p2v-client/pkg/%{gemname}-%{version}.gem
++ --force --rdoc p2v/client/pkg/%{gemname}-%{version}.gem
+ mv %{buildroot}%{gemdir}/bin/* %{buildroot}/%{_bindir}
+ find %{buildroot}%{geminstdir}/bin -type f | xargs chmod a+x
+ cp COPYING %{buildroot}/%{geminstdir}
+@@ -207,8 +207,8 @@
+ %global builderdir %{_datadir}/virt-p2v-image-builder
+ builder=%{buildroot}/%{_bindir}/virt-p2v-image-builder
+ mkdir -p %{buildroot}%{builderdir}
+-cp p2v-image-builder/*.ks %{buildroot}%{builderdir}
+-cp p2v-image-builder/virt-p2v-image-builder $builder
++cp p2v/image-builder/*.ks %{buildroot}%{builderdir}
++cp p2v/image-builder/virt-p2v-image-builder $builder
+
+ # Set the default data directory
+ sed -i -e 's,^DEFAULT_DATADIR=.*,DEFAULT_DATADIR=%{builderdir},' $builder
+@@ -217,7 +217,7 @@
+ %check
+ ./Build test
+
+-pushd p2v-client
++pushd p2v/client
+ # No tests yet
+ #rake test
+ popd
diff --git a/virt-v2v-0.8.1-01-e34a8c09.patch b/virt-v2v-0.8.1-01-e34a8c09.patch
new file mode 100644
index 0000000..58b03a3
--- /dev/null
+++ b/virt-v2v-0.8.1-01-e34a8c09.patch
@@ -0,0 +1,57 @@
+commit e34a8c0911f53cff64f9a33d3802ac7361f3fe19
+Author: Matthew Booth <mbooth at redhat.com>
+Date: Wed May 11 16:05:18 2011 +0100
+
+ p2v-client: Drop echoe for build
+
+ echoe changes incompatibly from F14->F15. We're not using the vast majority of
+ its features, and it remains completely undocumented as far as I can tell. This
+ patch drops it in favour of a simple, explicit gem build task.
+
+diff --git a/p2v/client/Rakefile b/p2v/client/Rakefile
+index d190f08..23c26f5 100644
+--- a/p2v/client/Rakefile
++++ b/p2v/client/Rakefile
+@@ -14,24 +14,10 @@
+ # along with this program; if not, write to the Free Software
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+-require 'rubygems'
+-require 'echoe'
++require 'rake'
++require 'rake/gempackagetask'
+
+-Echoe.new("virt-p2v") do |p|
+- p.project = "Virt P2V"
+- p.version = `../../Build version`
+- p.author = "Matthew Booth"
+- p.summary = "Send a machine's storage and metadata to virt-p2v-server"
+- p.description = <<EOF
+-virt-p2v is a client which connects to a virt-p2v-server and transfer's the host
+-machine's storage and metadata. virt-p2v is intended to be run from a live
+-image, so it is unlikely you want to install it.
+-EOF
+- p.url = "http://libguestfs.org"
+- p.email = "libguestfs at redhat.com"
+- p.runtime_dependencies = [
+- 'gtk2',
+- 'gettext',
+- 'net-ssh'
+- ]
+-end
++task :default => :gem
++
++load 'virt-p2v.gemspec'
++Rake::GemPackageTask.new(GEMSPEC) {}
+diff --git a/virt-v2v.spec.PL b/virt-v2v.spec.PL
+index 2249b01..6a155e2 100644
+--- a/virt-v2v.spec.PL
++++ b/virt-v2v.spec.PL
+@@ -79,7 +79,6 @@ BuildRequires: perl-hivex >= 1.2.2
+
+ # virt-p2v build requirements
+ BuildRequires: rubygem(rake)
+-BuildRequires: rubygem(echoe)
+
+ Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
+
diff --git a/virt-v2v-0.8.1-02-fadb1929.patch b/virt-v2v-0.8.1-02-fadb1929.patch
new file mode 100644
index 0000000..8fc6c4a
--- /dev/null
+++ b/virt-v2v-0.8.1-02-fadb1929.patch
@@ -0,0 +1,111 @@
+commit fadb1929b4a8447a719a34f07e5934badf694f45
+Author: Matthew Booth <mbooth at redhat.com>
+Date: Wed May 11 16:46:37 2011 +0100
+
+ p2v-client: Add missing gemspec
+
+ gemspec used to be auto-generated, so was explicitly ignored. It's no longer
+ auto-generated, so we need it.
+
+diff --git a/p2v/client/virt-p2v.gemspec b/p2v/client/virt-p2v.gemspec
+new file mode 100644
+index 0000000..d8edde8
+--- /dev/null
++++ b/p2v/client/virt-p2v.gemspec
+@@ -0,0 +1,96 @@
++# Copyright (C) 2011 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++V2V_VERSION = `../../Build version`
++abort "Failed to get version" unless $? == 0
++
++GEMSPEC = Gem::Specification.new do |s|
++ s.name = %q{virt-p2v}
++ s.version = V2V_VERSION
++
++ s.authors = ["Matthew Booth"]
++ s.date = %q{2011-05-10}
++ s.summary = %q{Send a machine's storage and metadata to virt-p2v-server}
++ s.description = %q{
++ virt-p2v is a client which connects to a virt-p2v-server and transfer's
++ the host machine's storage and metadata. virt-p2v is intended to be run
++ from a live image, so it is unlikely you want to install it.
++ }
++ s.email = %q{libguestfs at redhat.com}
++ s.homepage = %q{http://libguestfs.org}
++
++ s.default_executable = %q{virt-p2v}
++ s.executables = ["virt-p2v"]
++ s.files = [
++ "Rakefile",
++ "bin/virt-p2v",
++ "lib/virt-p2v/blockdevice.rb",
++ "lib/virt-p2v/connection.rb",
++ "lib/virt-p2v/converter.rb",
++ "lib/virt-p2v/gtk-queue.rb",
++ "lib/virt-p2v/netdevice.rb",
++ "lib/virt-p2v/ui/connect.rb",
++ "lib/virt-p2v/ui/convert.rb",
++ "lib/virt-p2v/ui/main.rb",
++ "lib/virt-p2v/ui/network.rb",
++ "lib/virt-p2v/ui/p2v.ui",
++ "lib/virt-p2v/ui/success.rb",
++ "virt-p2v.gemspec",
++ "Manifest"
++ ]
++ s.require_paths = ["lib"]
++
++ if s.respond_to? :specification_version then
++ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
++ s.specification_version = 3
++
++ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
++ s.add_runtime_dependency(%q<gtk2>, [">= 0"])
++ s.add_runtime_dependency(%q<gettext>, [">= 0"])
++ s.add_runtime_dependency(%q<net-ssh>, [">= 0"])
++ else
++ s.add_dependency(%q<gtk2>, [">= 0"])
++ s.add_dependency(%q<gettext>, [">= 0"])
++ s.add_dependency(%q<net-ssh>, [">= 0"])
++ end
++ else
++ s.add_dependency(%q<gtk2>, [">= 0"])
++ s.add_dependency(%q<gettext>, [">= 0"])
++ s.add_dependency(%q<net-ssh>, [">= 0"])
++ end
++
++# Source doesn't contain any rdoc
++# s.extra_rdoc_files = [
++# "bin/virt-p2v",
++# "lib/virt-p2v/blockdevice.rb",
++# "lib/virt-p2v/connection.rb",
++# "lib/virt-p2v/converter.rb",
++# "lib/virt-p2v/gtk-queue.rb",
++# "lib/virt-p2v/netdevice.rb",
++# "lib/virt-p2v/ui/connect.rb",
++# "lib/virt-p2v/ui/convert.rb",
++# "lib/virt-p2v/ui/main.rb",
++# "lib/virt-p2v/ui/network.rb",
++# "lib/virt-p2v/ui/p2v.ui",
++# "lib/virt-p2v/ui/success.rb"
++# ]
++# s.rdoc_options = [
++# "--line-numbers",
++# "--inline-source",
++# "--title",
++# "Virt-p2v"
++# ]
++end
diff --git a/virt-v2v.spec b/virt-v2v.spec
index 645e393..20f99e2 100644
--- a/virt-v2v.spec
+++ b/virt-v2v.spec
@@ -16,6 +16,10 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
# local seq no: the order the patches should be applied in
# git commit: the first 8 characters of the git commit hash
+Patch0: virt-v2v-0.8.1-00-44eb9021-modified.patch
+Patch1: virt-v2v-0.8.1-01-e34a8c09.patch
+Patch2: virt-v2v-0.8.1-02-fadb1929.patch
+
# Unfortunately, despite really being noarch, we have to make virt-v2v arch
# dependent to avoid build failures on architectures where libguestfs isn't
# available.
@@ -53,7 +57,6 @@ BuildRequires: perl-hivex >= 1.2.2
# virt-p2v build requirements
BuildRequires: rubygem(rake)
-BuildRequires: rubygem(echoe)
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
@@ -135,11 +138,16 @@ virt-p2v-image-builder is a tool to create a bootable virt-p2v live image.
%prep
%setup -q -n %{name}-v%{version}
+%patch0 -p1
+%patch1 -p1
+%patch2 -p1
+
+
%build
%{__perl} Build.PL
./Build
-pushd p2v-client
+pushd p2v/client
rake gem
popd
@@ -172,7 +180,7 @@ mkdir -p %{buildroot}/%{_bindir}
mkdir -p %{buildroot}/%{gemdir}
gem install --local --install-dir %{buildroot}%{gemdir} \
- --force --rdoc p2v-client/pkg/%{gemname}-%{version}.gem
+ --force --rdoc p2v/client/pkg/%{gemname}-%{version}.gem
mv %{buildroot}%{gemdir}/bin/* %{buildroot}/%{_bindir}
find %{buildroot}%{geminstdir}/bin -type f | xargs chmod a+x
cp COPYING %{buildroot}/%{geminstdir}
@@ -181,8 +189,8 @@ cp COPYING %{buildroot}/%{geminstdir}
%global builderdir %{_datadir}/virt-p2v-image-builder
builder=%{buildroot}/%{_bindir}/virt-p2v-image-builder
mkdir -p %{buildroot}%{builderdir}
-cp p2v-image-builder/*.ks %{buildroot}%{builderdir}
-cp p2v-image-builder/virt-p2v-image-builder $builder
+cp p2v/image-builder/*.ks %{buildroot}%{builderdir}
+cp p2v/image-builder/virt-p2v-image-builder $builder
# Set the default data directory
sed -i -e 's,^DEFAULT_DATADIR=.*,DEFAULT_DATADIR=%{builderdir},' $builder
@@ -191,7 +199,7 @@ sed -i -e 's,^DEFAULT_DATADIR=.*,DEFAULT_DATADIR=%{builderdir},' $builder
%check
./Build test
-pushd p2v-client
+pushd p2v/client
# No tests yet
#rake test
popd
More information about the scm-commits
mailing list