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 + + * 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 * 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 @@ + + + + + + False + center-always + False + + + + True + 0 + 0 + + + 800 + 600 + True + 0 + 0 + in + + + True + vertical + 2 + + + True + + + True + 0 + 0 + 5 + 5 + <span weight='bold' foreground='white' size='xx-large'>virt-p2v</span> + True + + + + + False + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 800 + 550 + + + True + vertical + + + True + 0 + 1 + 11 + Welcome to virt-p2v. + + + False + 0 + + + + + True + 0 + out + + + True + True + automatic + automatic + + + True + True + network_device_list + False + 0 + + + Device + + + + 3 + 0 + + + + + + + 18 + MAC Address + + + + 3 + 1 + + + + + + + Status + + + + 3 + 2 + + + + + + + + + + + True + <b>Select a network device</b> + True + + + + + 1 + + + + + True + 0 + in + + + True + 12 + + + True + vertical + + + Automatic configuration + True + True + False + True + True + + + + 0 + + + + + True + False + 3 + 2 + 2 + + + True + 0 + IP Address: + + + GTK_FILL + GTK_FILL + + + + + True + 0 + Gateway: + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + 0 + DNS Servers: + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True + True + 39 + 39 + True + + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + 35 + + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + 2 + + + True + True + 39 + 39 + True + + + + 0 + + + + + True + 0 + Prefix: + + + False + 1 + + + + + True + True + 2 + 2 + True + + + + False + 2 + + + + + 1 + 2 + GTK_FILL + + + + + 1 + + + + + + + + + True + <b>IP Configuration</b> + True + + + + + False + 2 + + + + + True + 1 + 0 + + + Use these network settings + True + False + True + True + + + + + + False + 3 + + + + + + + + + True + vertical + + + True + 0 + 0 + + + True + 0 + in + + + True + 12 + + + True + vertical + + + True + 3 + 2 + 2 + + + True + 0 + Hostname: + + + + + + + + + True + 0 + Username: + + + 1 + 2 + + + + + + + True + 0 + Password: + + + 2 + 3 + + + + + + + True + True + + 40 + + + + 1 + 2 + + + + + + True + True + False + + 40 + + + + 1 + 2 + 2 + 3 + + + + + + True + True + + 40 + root + + + + 1 + 2 + 1 + 2 + + + + + + False + 0 + + + + + True + 0 + 0 + 8 + 8 + + + + + + 1 + + + + + + + + + True + <b>Connect to conversion server</b> + True + + + + + + + 0 + + + + + True + 1 + 0 + 0 + 0 + + + Connect + True + False + True + True + + + + + + False + 1 + + + + + + + + + True + vertical + + + True + + + True + 0 + out + + + True + 0 + 0 + 0 + 0 + 12 + + + True + 4 + 2 + 2 + + + True + 0 + Destination Profile: + + + + + True + convert_profile_list + + + + + 0 + + + + + 1 + 2 + + + + + True + 0 + Memory (MB): + + + 3 + 4 + + + + + True + True + + True + + + + 1 + 2 + 3 + 4 + + + + + True + 0 + Number of CPUs: + + + 2 + 3 + + + + + True + 0 + Name + + + 1 + 2 + + + + + True + True + + True + + + + 1 + 2 + 1 + 2 + + + + + True + True + + True + + + + 1 + 2 + 2 + 3 + + + + + + + + + True + <b>Target properties</b> + True + + + + + False + False + 0 + + + + + True + vertical + + + True + 0 + out + + + True + + + True + True + automatic + automatic + + + True + True + convert_fixed_list + False + 0 + + + Convert + True + + + + + + 0 + + + + + + + Device + + + + 1 + + + + + + + Transfer Progress + True + + + + 2 + + + + + + + + + + + + + True + <b>Fixed Storage</b> + True + + + + + 0 + + + + + True + 0 + out + + + True + + + True + True + automatic + automatic + + + True + True + convert_removable_list + + + Convert + + + + + + 0 + + + + + + + Device + + + + 1 + + + + + + + Type + + + + 2 + + + + + + + + + + + + + True + <b>Removable Media</b> + True + + + + + 1 + + + + + True + 0 + out + + + True + 1 + 1 + + + True + True + automatic + automatic + + + True + True + convert_network_list + False + 0 + + + Convert + + + + + + 0 + + + + + + + Device + + + + 1 + + + + + + + + + + + + + True + <b>Network Interfaces</b> + True + + + + + 2 + + + + + 1 + + + + + 0 + + + + + True + + + True + 0 + 12 + + + + + + 0 + + + + + Convert + True + True + True + + + + False + False + 1 + + + + + False + False + 1 + + + + + + + + + True + vertical + + + True + A guest has been successfully created on the target server. + +Remove the temporary boot device from this machine and press 'Reboot' to continue. + center + + + 0 + + + + + True + 0.25 + 0.25 + + + Reboot + True + True + True + + + + + + 1 + + + + + + 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 = < /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 - 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 < /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 < $INSTALL_ROOT/etc/$PACKAGE-release <> $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 < + +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, +L. + +=head1 AUTHOR + +Matthew Booth + +=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 @@ - - - - - - False - center-always - False - - - - True - 0 - 0 - - - 800 - 600 - True - 0 - 0 - in - - - True - vertical - 2 - - - True - - - True - 0 - 0 - 5 - 5 - <span weight='bold' foreground='white' size='xx-large'>virt-p2v</span> - True - - - - - False - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 800 - 550 - - - True - vertical - - - True - 0 - 1 - 11 - Welcome to virt-p2v. - - - False - 0 - - - - - True - 0 - out - - - True - True - automatic - automatic - - - True - True - network_device_list - False - 0 - - - Device - - - - 3 - 0 - - - - - - - 18 - MAC Address - - - - 3 - 1 - - - - - - - Status - - - - 3 - 2 - - - - - - - - - - - True - <b>Select a network device</b> - True - - - - - 1 - - - - - True - 0 - in - - - True - 12 - - - True - vertical - - - Automatic configuration - True - True - False - True - True - - - - 0 - - - - - True - False - 3 - 2 - 2 - - - True - 0 - IP Address: - - - GTK_FILL - GTK_FILL - - - - - True - 0 - Gateway: - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - 0 - DNS Servers: - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - True - 39 - 39 - True - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - 35 - - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - 2 - - - True - True - 39 - 39 - True - - - - 0 - - - - - True - 0 - Prefix: - - - False - 1 - - - - - True - True - 2 - 2 - True - - - - False - 2 - - - - - 1 - 2 - GTK_FILL - - - - - 1 - - - - - - - - - True - <b>IP Configuration</b> - True - - - - - False - 2 - - - - - True - 1 - 0 - - - Use these network settings - True - False - True - True - - - - - - False - 3 - - - - - - - - - True - vertical - - - True - 0 - 0 - - - True - 0 - in - - - True - 12 - - - True - vertical - - - True - 3 - 2 - 2 - - - True - 0 - Hostname: - - - - - - - - - True - 0 - Username: - - - 1 - 2 - - - - - - - True - 0 - Password: - - - 2 - 3 - - - - - - - True - True - - 40 - - - - 1 - 2 - - - - - - True - True - False - - 40 - - - - 1 - 2 - 2 - 3 - - - - - - True - True - - 40 - root - - - - 1 - 2 - 1 - 2 - - - - - - False - 0 - - - - - True - 0 - 0 - 8 - 8 - - - - - - 1 - - - - - - - - - True - <b>Connect to conversion server</b> - True - - - - - - - 0 - - - - - True - 1 - 0 - 0 - 0 - - - Connect - True - False - True - True - - - - - - False - 1 - - - - - - - - - True - vertical - - - True - - - True - 0 - out - - - True - 0 - 0 - 0 - 0 - 12 - - - True - 4 - 2 - 2 - - - True - 0 - Destination Profile: - - - - - True - convert_profile_list - - - - - 0 - - - - - 1 - 2 - - - - - True - 0 - Memory (MB): - - - 3 - 4 - - - - - True - True - - True - - - - 1 - 2 - 3 - 4 - - - - - True - 0 - Number of CPUs: - - - 2 - 3 - - - - - True - 0 - Name - - - 1 - 2 - - - - - True - True - - True - - - - 1 - 2 - 1 - 2 - - - - - True - True - - True - - - - 1 - 2 - 2 - 3 - - - - - - - - - True - <b>Target properties</b> - True - - - - - False - False - 0 - - - - - True - vertical - - - True - 0 - out - - - True - - - True - True - automatic - automatic - - - True - True - convert_fixed_list - False - 0 - - - Convert - True - - - - - - 0 - - - - - - - Device - - - - 1 - - - - - - - Transfer Progress - True - - - - 2 - - - - - - - - - - - - - True - <b>Fixed Storage</b> - True - - - - - 0 - - - - - True - 0 - out - - - True - - - True - True - automatic - automatic - - - True - True - convert_removable_list - - - Convert - - - - - - 0 - - - - - - - Device - - - - 1 - - - - - - - Type - - - - 2 - - - - - - - - - - - - - True - <b>Removable Media</b> - True - - - - - 1 - - - - - True - 0 - out - - - True - 1 - 1 - - - True - True - automatic - automatic - - - True - True - convert_network_list - False - 0 - - - Convert - - - - - - 0 - - - - - - - Device - - - - 1 - - - - - - - - - - - - - True - <b>Network Interfaces</b> - True - - - - - 2 - - - - - 1 - - - - - 0 - - - - - True - - - True - 0 - 12 - - - - - - 0 - - - - - Convert - True - True - True - - - - False - False - 1 - - - - - False - False - 1 - - - - - - - - - True - vertical - - - True - A guest has been successfully created on the target server. - -Remove the temporary boot device from this machine and press 'Reboot' to continue. - center - - - 0 - - - - - True - 0.25 - 0.25 - - - Reboot - True - True - True - - - - - - 1 - - - - - - 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 = <= 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@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, [">= 0"]) - s.add_runtime_dependency(%q, [">= 0"]) - s.add_runtime_dependency(%q, [">= 0"]) - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - end - else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 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 - 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 < /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 < $INSTALL_ROOT/etc/$PACKAGE-release <> $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 < - -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, -L. - -=head1 AUTHOR - -Matthew Booth - -=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