# General configuration
PACKAGE := virt-p2v
-VERSION := 0.4
+VERSION := 0.5
# i386 images also work on x86-64, so best to stick with i386.
ARCH := i386
-e 's|@TIMEZONE@|$(TIMEZONE)|g' \
< $< | cat - livecd-post.sh > $@
-livecd-post.sh: livecd-post.sh.in p2v.init virt-p2v.sh inittab lvm.conf Makefile
+livecd-post.sh: livecd-post.sh.in virt-p2v.sh inittab lvm.conf Makefile
rm -f $@
sed \
- -e '/@P2V.INIT@/ r p2v.init' \
- -e '/@P2V.INIT@/ d' \
-e '/@VIRT-P2V.SH@/ r virt-p2v.sh' \
-e '/@VIRT-P2V.SH@/ d' \
-e '/@INITTAB@/ r inittab' \
qemu -m 512 -cdrom virt-p2v-0.1.iso -boot d -hda rhel5gax32fv.img
-Network daemon
+TCP transport and network daemon
----------------------------------------------------------------------
+
+The preferred transport is ssh, but if you cannot use this then there
+is an alternate TCP transport. (This transport is not encrypted).
+
+On the Xen host or staging server, install NetCat (the 'nc' command,
+in Fedora and RHEL the package is also called 'nc').
+
+Choose a free port number and make sure that it is not firewalled.
+
+Then run:
+
+ nc -kl PORT > disks
+
+where PORT is replaced by the port number chosen above.
+
+After p2v has completed the 'disks' file will contain compressed
+images of one or more disks. There is a Perl script called
+virt-p2v-unpack which can unpack the file:
+
+ virt-p2v-unpack disks
dd if=/dev/disk | gzip | nc xenhost port
and on the remote host they do:
- nc -l port > /var/lib/xen/images/disks.gz
+ nc -kl port > /var/lib/xen/images/disks
For (c) we can use device-mapper snapshots to mount a ramdisk above
the disks themselves. This allows us to make non-destructive changes
# Custom inittab for p2v livecd.
-id:5:initdefault:
+id:3:initdefault:
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
+# Run virt-p2v.sh on tty1
+1:3:once:/usr/bin/virt-p2v.sh tty1
+
# Run gettys but not on tty1 which is where virt-p2v runs.
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
#
# $Id$
-# Create a 'p2v' init script which runs last thing during the
-# boot.
-
-cat > /etc/init.d/p2v << '__EOF4321__'
-@P2V.INIT@
-__EOF4321__
-
-# Make the 'p2v' script run when the live CD boots.
-chmod 0755 /etc/init.d/p2v
-/sbin/restorecon /etc/init.d/p2v
-/sbin/chkconfig --add p2v
+# This is the virt-p2v shell script.
cat > /usr/bin/virt-p2v.sh << '__EOF1234__'
@VIRT-P2V.SH@
+++ /dev/null
-#!/bin/bash
-#
-# p2v: Init script which starts the p2v process.
-#
-# chkconfig: 345 99 99
-# description: Init script which starts the p2v process.
-
-. /etc/init.d/functions
-
-# How were we called?
-case "$1" in
-start)
- # Some modules which we definitely will need.
- /sbin/modprobe dm_mod
- /sbin/modprobe dm_snapshot
-
- # Start the P2V script.
- /usr/bin/virt-p2v.sh &
-
- ;;
-
-*) ;;
-esac
-
-# This file must end with a newline
-
--- /dev/null
+#!/usr/bin/perl -w
+#
+# Unpack disks from TCP transport.
+#
+# Copyright (C) 2007 Red Hat Inc.
+# Written by Richard W.M. Jones <rjones@redhat.com>
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# $Id$
+
+use strict;
+
+use Getopt::Long;
+use Pod::Usage;
+
+my $outputdir = ".";
+my $force = 0;
+my $noninteractive = 0;
+
+sub main {
+ my $help = 0;
+ my $man = 0;
+
+ Getopt::Long::Configure ("bundling");
+
+ GetOptions (
+ "d|directory=s", \$outputdir,
+ "f|force", \$force,
+ "n|noninteractive", \$noninteractive,
+ "<>" => \&process,
+ "help" => \$help, man => \$man,
+ ) or pod2usage (2);
+ pod2usage (1) if $help;
+ pod2usage (-exitstatus => 0, -verbose => 2) if $man;
+
+ exit 0
+}
+
+# Process each input file.
+
+sub process {
+ my $filename = shift;
+
+ open DISKS,"$filename" or die "$filename: $!";
+ my $zcat_open = 0; # If we have a pipe open to zcat now.
+ my $newline_chomped = 0; # If we need to add a \n
+ my $lineno = 0; # Current line number.
+ while (<DISKS>) {
+ $lineno++;
+ chomp;
+
+ # Is it a header for the next disk image?
+ if (/^p2v (.*) (\d+)$/) {
+ my $imagename = $1;
+ my $sectors = $2;
+
+ # Close the previous file (if open).
+ close ZCAT if $zcat_open;
+
+ # Check the image name.
+ if (!$force &&
+ ($imagename =~ /\.\./ || $imagename =~ m{/} ||
+ $imagename !~ /^[-.A-Za-z0-9]+$/)) {
+ print "$filename: bad image name at line $lineno: $imagename\n";
+ exit 2;
+ }
+ $imagename = $outputdir . "/" . $imagename;
+
+ if (!$force && -f $imagename) {
+ print "$filename: disk image already exists at line $lineno: $imagename\n";
+ exit 2;
+ }
+
+ if (!$noninteractive) {
+ print "Write disk image $imagename ($sectors sectors)? (y/n) ";
+ my $key = <STDIN>;
+ exit 3 if $key =~ /^n/i;
+ }
+
+ open ZCAT, "| zcat > $imagename" or die "zcat: $!";
+ $zcat_open = 1;
+ $newline_chomped = 0;
+ }
+ # Otherwise we're in the middle of data.
+ else {
+ if (!$zcat_open) {
+ print "$filename: corrupt data at line $lineno\n";
+ exit 2
+ }
+ print ZCAT "\n" if $newline_chomped;
+ print ZCAT;
+ $newline_chomped = 1; # For the next newline.
+ }
+ }
+
+ close ZCAT if $zcat_open;
+ close DISKS;
+
+
+}
+
+main ()
#
# $Id$
+# Because we're running from a start-up script, we don't have much
+# of a login environment, so set one up.
export PATH=/usr/sbin:/sbin:/usr/local/bin:/usr/kerberos/bin:/usr/bin:/bin
+export HOME=/root
+export LOGNAME=root
# The defaults here make a generic virt-p2v.sh script, but if you want
# to build a partially-/fully-automatic P2V solution, then you can set
# Use the function read_line instead of the shell built-in read.
# It reads from the console.
function read_line {
- read "$*" </dev/console
+ read "$*"
}
# Launch a bash subshell connected to the console.
function shell {
- PS1='\u@\h:\w\$ ' bash </dev/console >/dev/console 2>&1
+ PS1='\u@\h:\w\$ ' bash
}
#----------------------------------------------------------------------
echo "(Hint: if not sure, there is a shell on console [ALT] [F2])"
echo -n " (y/n) "
local line
- read_line line </dev/console
+ read_line line
if [ "$line" = "y" -o "$line" = "yes" ]; then return 0; fi
return 1
fi
#----------------------------------------------------------------------
# General script setup.
+log
+log virt-p2v starting up at `date`
+
+# The first and only parameter must be the tty. Connect
+# stdin/stdout/stderr to this device.
+if [ -n "$1" ]; then
+ log connecting to /dev/$1
+ exec </dev/$1 &>/dev/$1
+fi
+
# We can safely write files into /tmp without modifying anything.
cd /tmp
#----------------------------------------------------------------------
# Dialog with the user.
-log
-log virt-p2v starting up at `date`
-
if [ "$greeting" != "no" ]; then
dialog \
--title "virt-p2v" \
;;
tcp)
echo "p2v $name $sectors" > header
- cat header - | nc "$remote_host" "$remote_port"
+ echo > newline
+ cat header - newline | nc "$remote_host" "$remote_port"
;;
esac
done