From: Richard W.M. Jones <"Richard W.M. Jones "> Date: Sat, 2 Feb 2008 15:41:28 +0000 (+0000) Subject: Remove old shell-script version, and obsolete old server. X-Git-Url: http://git.annexia.org/?a=commitdiff_plain;h=f303b481264226d5bd2a8ff4ca7463afba56a093;p=virt-p2v.git Remove old shell-script version, and obsolete old server. --- diff --git a/virt-p2v-unpack b/virt-p2v-unpack deleted file mode 100755 index ad3b702..0000000 --- a/virt-p2v-unpack +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/perl -w -# -# Unpack disks from TCP transport. -# -# Copyright (C) 2007 Red Hat Inc. -# Written by Richard W.M. Jones -# -# 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; - -XXX This needs a rewrite - -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 () { - $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 = ; - 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 () diff --git a/virt-p2v.sh b/virt-p2v.sh deleted file mode 100755 index 2bc82a4..0000000 --- a/virt-p2v.sh +++ /dev/null @@ -1,702 +0,0 @@ -#!/bin/bash -# -# virt-p2v.sh is a shell script which performs a physical to -# virtual conversion of local disks. -# -# Copyright (C) 2007 Red Hat Inc. -# Written by Richard W.M. Jones -# -# 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$ - -# 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 -# these variables to something, and the script won't ask the user for -# input. - -# Use 'greeting=no' to suppress greeting and final verification screens. -greeting= - -override_remote_host= -override_remote_port= - -# can be 'ssh' or 'tcp' -override_remote_transport= - -# eg. override_remote_directory=/var/lib/xen/images -# (only if override_remote_transport is 'ssh') -override_remote_directory= - -# list of local physical devices to send, separated by spaces, -# if empty ask user. -# this is usually a list of whole disk devices (eg. "sda") -override_devices_to_send="" - -# the root filesystem containing /etc/fstab (eg. "sda3" or -# "VolGroup00/LogVol00") -override_root_filesystem="" - -# network configuration -# - if empty, ask user -# - "auto" means try to autoconfigure from root filesystem -# (XXX needs to contain more ways to override in future) -override_network="" - -#---------------------------------------------------------------------- -# General script setup and logging. - -exec 2>> /tmp/virt-p2v.log - -function log { - echo "$@" 1>&2 -} - -log -log virt-p2v starting up at `date` - -# The first and only parameter must be the tty. Connect -# stdin/stdout to this device. -if [ -n "$1" ]; then - log connecting to /dev/$1 - exec /dev/$1 -fi - -# We can safely write files into /tmp without modifying anything. -cd /tmp - -#---------------------------------------------------------------------- -# Helper functions. - -# 'matches_regexp regexp string' returns true if string matches regexp. -# It uses egrep for extended regexps. -function matches_regexp { - local re="$1"; shift - echo "$@" | grep -Esq "$re" -} - -# 'string_contains needle haystack' returns true if needle in haystack. -function string_contains { - echo "$2" | grep -Fsq "$1" -} - -# 'word_in_list word ...'. '...' (list of parameters) is a list of -# words. Returns true if 'word' is in the list. -function word_in_list { - local word="$1"; shift - local w - for w in "$@"; do - [ "$w" = "$word" ] && return 0 - done - return 1 -} - -#---------------------------------------------------------------------- -# I/O functions - -# Use the function read_line instead of the shell built-in read. -# It reads from the console. -function read_line { - read "$*" -} - -# Launch a bash subshell connected to the console. -function shell { - PS1='\u@\h:\w\$ ' bash -} - -#---------------------------------------------------------------------- -# Device mapper snapshotting. - -next_ramdisk=1 - -# Create a device-mapper snapshot of a device with ramdisk overlay. -# Example: -# snapshot sda1 snap -# creates a snapshot of /dev/sda1 called /dev/mapper/snap -function snapshot { - local dev=$1 name=$2 - - # Next free ramdisk (/dev/ram$i) - local i=$next_ramdisk - next_ramdisk=$(($next_ramdisk+1)) - - # Get size of the device in sectors. - local sectors=`blockdev --getsize /dev/$dev` - - dmsetup create ${name}_org \ - --table="0 $sectors snapshot-origin /dev/$dev" - if [ $? -ne 0 ]; then exit 1; fi - dmsetup create $name \ - --table="0 $sectors snapshot /dev/mapper/${name}_org /dev/ram$i n 64" - if [ $? -ne 0 ]; then exit 1; fi -} - -# Drop an existing snapshot created by snapshot function. -# Example: -# drop_snapshot snap -# drops a snapshot called /dev/mapper/snap -function drop_snapshot { - local name=$1 - - dmsetup remove /dev/mapper/$name - dmsetup remove /dev/mapper/${name}_org -} - -#---------------------------------------------------------------------- -# Searching for devices, partitions and LVs. - -# Convert "/dev/foo" into "foo". Returns $device. -function strip_slash_dev { - device=$(echo "$1" | sed 's|^/dev/||') -} - -# The 'lvs' utility returns devices like '/dev/sda2(0)'. I've no -# idea what the number in parentheses is, but remove /dev/ and the -# strange number. -function device_of_lvs_device { - strip_slash_dev "$1" - device=$(echo "$device" | sed 's|(.*)$||') -} - -# All functions in this section assume that physical block devices -# (things corresponding to hard disks in the system) are called -# hd[a-z]+ or sd[a-z]+ - -# Get list of physical block devices. Sets variable $devices -# to something like "sda sdb". -function search_devices { - devices1=$(cd /sys/block && /bin/ls -d [hs]d*) - log search_devices: devices1: $devices1 - # Ignore devices which fail 'blockdev --getsize' - probably - # removable devices or other strange ones. - devices="" - for d in $devices1; do - if blockdev --getsize /dev/$d > /dev/null; then - devices="$devices${devices:+ }$d" - fi - done - log search_devices: devices: $devices -} - -# Get list of partitions from a physical block device. Sets -# variable $partitions to something like "sda1 sda2 sda3". -# See also: search_parts -function get_partitions { - partitions=$(cd /sys/block/"$1" && /bin/ls -d "$1"*) -} - -# Given a partition (eg. "sda1" or "VolGroup00/LogVol00") return -# the physical block device which contains it. In the case where -# we are given an LV, this is supposed to do the right thing and -# go back through the layers until it gets to the physical block -# device. Returns $device set to something like "sda". -function block_device_of_part { - local part="$1" vg_name lv_name pv - - if matches_regexp '^[hs]d[a-z]+[0-9]*$' "$part"; then - device=$(echo "$part" | sed 's|[0-9]*$||') - return 0 - fi - - # Not a partition name, so it's a LV name. Ask lvs to - # do the hard work. - lvs --noheadings -o vg_name,lv_name,devices > lvs - while read vg_name lv_name pv; do - if [ "$vg_name/$lv_name" = "$part" \ - -o "mapper/$vg_name-$lv_name" = "$part" ]; then - device_of_lvs_device "$pv" ;# sets $device to (eg.) "sda1" - block_device_of_part "$device" - return 0 - fi - done < lvs - - # Help ... block device not found. - log block_device_of_part: block device cannot be resolved: $part - device="$part" -} - -# search_parts $devices examines the list of devices and looks for -# partitions or LVs on just those devices. Sets variable $parts to -# something like "sda1 VolGroup00/LogVol00". -function search_parts { - local vg_name lv_name pv pvs="" device partition partitions - - parts="" - - lvs --noheadings -o vg_name,lv_name,devices > lvs - while read vg_name lv_name pv; do - # Get just the partition name (eg. "sda2"). - device_of_lvs_device "$pv"; pv="$device" - # Get just the block device name (eg. "sda"). - block_device_of_part "$pv" - - log search_parts: pv $pv device $device lv $vg_name/$lv_name - - # A device in our list of devices to consider? - if word_in_list $device "$@"; then - log search_parts: adding $vg_name/$lv_name - parts="$parts $vg_name/$lv_name" - pvs="$pvs $pv" - fi - done < lvs - - log search_parts: after lvs, parts $parts pvs $pvs - - # Look for non-LVM partitions, but ignore any which are PVs - # as identified above. - for device in "$@"; do - get_partitions "$device" - for partition in $partitions; do - if ! word_in_list $partition $pvs; then - log search_parts: adding $partition - parts="$parts $partition" - fi - done - done - - # $parts is returned. -} - -# This generates a snapshot device name from a device name. -# eg. sda -> snap_sda -# Sets $dname. -function snap_name { - dname=`echo -n snap_"$1" | tr -cs '[:alnum:]' _` -} - -#---------------------------------------------------------------------- -# Network configuration functions. - -# `auto_network' tries to configure the network from the -# root filesystem. Returns true or false. -function auto_network { - # Make sure this file exists, otherwise Fedora gives a warning. - touch /etc/resolv.conf - - pushd /etc/sysconfig - - mv network network.saved - mv networking networking.saved - mv network-scripts network-scripts.saved - - # Originally I symlinked these, but that causes dhclient to - # keep open /mnt/root (as its cwd is in network-scripts subdir). - # So now we will copy them recursively instead. - cp -r /mnt/root/etc/sysconfig/network . - cp -r /mnt/root/etc/sysconfig/networking . - cp -r /mnt/root/etc/sysconfig/network-scripts . - - /etc/init.d/network start - local status=$? - - rm -rf network networking network-scripts - mv network.saved network - mv networking.saved networking - mv network-scripts.saved network-scripts - - popd - - ping -c 3 $remote_host - - if [ "$greeting" != "no" ]; then - echo "Did automatic network configuration work?" - echo "(Hint: if not sure, there is a shell on console [ALT] [F2])" - echo -n " (y/n) " - local line - read_line line - if [ "$line" = "y" -o "$line" = "yes" ]; then return 0; fi - return 1 - fi - - # In non-interactive mode, return the status of /etc/init.d/network. - return $status -} - -#---------------------------------------------------------------------- -# Dialog with the user. - -if [ "$greeting" != "no" ]; then - dialog \ - --title "virt-p2v" \ - --msgbox "\nWelcome to virt-p2v, a live CD for migrating a physical machine to a virtualized host.\n\nTo continue press the Return key.\n\nTo get a shell you can use [ALT] [F2] and log in as root with no password." 17 50 -fi - -# Get configuration from the user. - -# To make the [Back] button work, we make this into a looping state -# machine. Each state asks a question and jumps to the next state -# (unless [Back] is pressed, in which case it jumps back to the previous -# state). Finally the 'exit' state causes us to quit the loop. - -remote_port=22 -remote_directory=/var/lib/xen/images -state=transport - -while [ "$state" != "exit" ]; do - log next state = $state - case "$state" in - transport) - if [ -n "$override_remote_transport" ]; then - remote_transport="$override_remote_transport" - state=hostname - else - case "$remote_transport" in - tcp) ssh_on=off; tcp_on=on;; - *) ssh_on=on; tcp_on=off;; - esac - dialog \ - --nocancel \ - --radiolist "Connection type" 10 50 2 \ - "ssh" "SSH (secure shell - recommended)" $ssh_on \ - "tcp" "TCP socket" $tcp_on \ - 2> line - remote_transport=`cat line` - state=hostname - fi - ;; - hostname) - if [ -n "$override_remote_host" ]; then - remote_host="$override_remote_host" - state=port - else - dialog \ - --extra-button --extra-label "Back" --nocancel \ - --inputbox "Remote host" 10 50 "$remote_host" \ - 2> line - if [ $? -eq 3 ]; then state=transport - else - remote_host=`cat line` - if [ -n "$remote_host" ]; then state=port; fi - # else stay in same state and demand a hostname! - fi - fi - ;; - port) - if [ -n "$override_remote_port" ]; then - remote_port="$override_remote_port" - state=directory - else - dialog \ - --extra-button --extra-label "Back" --nocancel \ - --inputbox "Remote port" 10 50 "$remote_port" \ - 2> line - if [ $? -eq 3 ]; then state=hostname - else - remote_port=`cat line` - state=directory - fi - fi - ;; - directory) - if [ "$remote_transport" = "tcp" ]; then - state=devices - elif [ -n "$override_remote_directory" ]; then - remote_directory="$override_remote_directory" - state=devices - else - dialog \ - --extra-button --extra-label "Back" --nocancel \ - --inputbox "Remote directory containing guest images" \ - 10 50 \ - "$remote_directory" \ - 2> line - if [ $? -eq 3 ]; then state=port - else - remote_directory=`cat line` - state=devices - fi - fi - ;; - - # Block devices configuration. - devices) - if [ -n "$override_devices_to_send" ]; then - devices_to_send="$override_devices_to_send" - state=root - else - # Returns the list of physical devices in $devices - search_devices - - log devices returned by search_devices: $devices - - deviceslist="" - for d in $devices; do - if word_in_list $d $devices_to_send; then - stat=on - else - stat=off - fi - log running blockdev --getsize /dev/$d - gigs=$(($(blockdev --getsize /dev/$d)/2/1024/1024)) - log /dev/$d has size $gigs - deviceslist="$deviceslist $d /dev/$d(${gigs}GB) $stat" - done - log deviceslist="$deviceslist" - - dialog \ - --extra-button --extra-label "Back" --nocancel \ - --single-quoted \ - --checklist "Pick disks to send" 15 50 8 \ - $deviceslist \ - 2> line - if [ $? -eq 3 ]; then state=directory - else - devices_to_send=`cat line` - state=root - fi - fi - ;; - - # Root filesystem. - root) - if [ -n "$override_root_filesystem" ]; then - root_filesystem="$override_root_filesystem" - state=network - else - # Returns the list of possible partitions / LVs in $parts - search_parts $devices_to_send - - log partitions returned by search_parts: $parts - - partslist="" - for r in $parts; do - if word_in_list $r $root_filesystem; then - stat=on - else - stat=off - fi - partslist="$partslist $r /dev/$r $stat" - done - - dialog \ - --extra-button --extra-label "Back" --nocancel \ - --single-quoted \ - --radiolist "Pick partition containing the root (/) filesystem" 10 70 5 \ - $partslist \ - 2> line - if [ $? -eq 3 ]; then state=devices - else - root_filesystem=`cat line` - state=network - fi - fi - ;; - - # Network configuration. - network) - if [ -n "$override_network" ]; then - network="$override_network" - state=verify - else - dialog \ - --extra-button --extra-label "Back" --nocancel \ - --radiolist "Network configuration" 10 70 5 \ - "auto" "Auto-configure from root filesystem" on \ - "ask" "Manual configuration" off \ - "sh" "Configure from the shell" off \ - 2> line - if [ $? -eq 3 ]; then state=root - else - network=`cat line` - state=verify - fi - fi - ;; - - # Verify configuration. - verify) - if [ "$greeting" = "no" ]; then - state=exit - else - dialog \ - --title "Summary" \ - --yesno "Transport: $remote_transport\nRemote host: $remote_host\nRemote port: $remote_port\nRemote directory (ssh only): $remote_directory\nDisks to send: $devices_to_send\nRoot filesystem: $root_filesystem\nNetwork configuration: $network\n\nProceed with these settings?" \ - 18 70 - if [ $? -eq 1 ]; then - state=transport - else - state=exit - fi - fi - ;; - *) - echo "Invalid state: $state" - state=transport - ;; - esac -done - -clear - -#---------------------------------------------------------------------- -# De-activate all volume groups and switch to new dm-only LVM config. -log deactivating volume groups - -vgchange -a n -mv /etc/lvm/lvm.conf /etc/lvm/lvm.conf.old -mv /etc/lvm/lvm.conf.new /etc/lvm/lvm.conf -rm -f /etc/lvm/cache/.cache - -# Snapshot the block devices. -for d in $devices_to_send; do - snap_name $d - log snapshotting block device /dev/$d to $dname ... - - snapshot $d $dname - - # The block devices are whole disks. Use kpartx to repartition them. - log running kpartx -a /dev/mapper/$dname ... - kpartx -a /dev/mapper/$dname -done - -# Rescan for LVs. -log running vgscan -vgscan -vgchange -a y - -# Mount the root filesystem on /mnt/root. If it's a physical -# device then we want to mount (eg) /dev/mapper/snap_sda2. -# If it's a LVM device then we can just mount the LVM partition. - -log mount $root_filesystem as /mnt/root - -snap_name $root_filesystem -root_filesystem_dname="$dname" - -if [ -b /dev/mapper/$root_filesystem_dname ]; then - mount /dev/mapper/$root_filesystem_dname /mnt/root -else - mount /dev/$root_filesystem /mnt/root -fi - -#---------------------------------------------------------------------- -# Now see if we can get a network configuration. -log network configuration $network - -case "$network" in - sh) - echo "Network configuration" - echo - echo "Please configure the network from this shell." - echo - echo "When finished, exit with ^D or exit" - echo - shell - ;; - - ask) - # XXX Not implemented - echo "Sorry, we didn't implement this one yet." - shell - ;; - - auto) - echo "Trying to auto-configure network from root filesystem ..." - echo - if ! auto_network; then - echo "Auto-configuration failed. Starting a shell." - echo - shell - fi -esac - -#---------------------------------------------------------------------- -# Rewrite /mnt/root/etc/fstab - -log rewriting /etc/fstab - -cp /mnt/root/etc/fstab /mnt/root/etc/fstab.p2vsaved -while read dev mountpoint fstype options freq passno; do - # If device is /dev/sd* then on the target fullvirt machine - # it will be /dev/hd* - if matches_regexp "^/dev/sd[[:alpha:]]+[[:digit:]]+$" "$dev"; then - dev=`echo $dev | sed 's|^/dev/sd|/dev/hd|'` - fi - - # Print out again with all the fields nicely lined up. - printf "%-23s %-23s %-7s %-15s %d %d\n" \ - "$dev" "$mountpoint" "$fstype" "$options" "$freq" "$passno" -done < /mnt/root/etc/fstab.p2vsaved > /mnt/root/etc/fstab - -#---------------------------------------------------------------------- -# XXX Look for other files which might need to be changed here ... - - - -# We've now finished with /mnt/root (the real root filesystem), -# so unmount it and synch everything. -umount /mnt/root -sync - -#---------------------------------------------------------------------- -# Send the device snapshots (underlying device + changes in ramdisk) -# to the remote server. - -log sending disks - -# XXX Effectively this is using the hostname derived from network -# configuration, but we might want to ask the user instead. -# XXX How do we ensure that we won't overwrite target files? Currently -# tries to use the current date as a uniquifier. - -# Names will be something like -# p2v-oirase-200709011249-hda.img -basename=p2v-`hostname -s|tr -cd '[0-9a-zA-Z]'`-`date +'%Y%m%d%H%M'` - -for dev in $devices_to_send; do - rdev=`echo $dev | sed 's|^sd|hd|'` - name="$basename-$rdev.img" - log sending $dev to $name - - snap_name $dev - - sectors=`blockdev --getsize /dev/mapper/$dname` - - gigs=$(($sectors/2/1024/1024)) - echo "Sending /dev/$dev (${gigs} GB) to remote machine" - - dd if=/dev/mapper/$dname | gzip --best | - case "$remote_transport" in - ssh) - ssh -p "$remote_port" "$remote_host" \ - "zcat > $remote_directory/$name" - ;; - tcp) - echo "p2v $name $sectors" > header - echo > newline - cat header - newline | nc "$remote_host" "$remote_port" - ;; - esac -done - - -#---------------------------------------------------------------------- -# Clean up. - -#for d in $devices_to_send; do -# snap_name $d -# kpartx -d /dev/mapper/$dname -# drop_snapshot $dname -#done - -# This file must end with a newline -