From 6d37b5f61c6cd4115197dc25e6d7ab571fcb3a54 Mon Sep 17 00:00:00 2001 From: rjones Date: Fri, 14 Sep 2007 17:03:41 +0100 Subject: [PATCH] Multiple updates. --- MANIFEST | 11 ++++ Makefile | 35 ++++++++++- README | 85 ++++++++++++++++++++++++++ README.developers | 8 ++- livecd-post.sh.in | 5 ++ livecd.ks.in | 2 + lvm.conf | 71 ++++++++++++++++++++++ virt-p2v.sh | 174 ++++++++++++++++++++++++++---------------------------- 8 files changed, 295 insertions(+), 96 deletions(-) create mode 100644 MANIFEST create mode 100644 lvm.conf diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..ae76ccd --- /dev/null +++ b/MANIFEST @@ -0,0 +1,11 @@ +.cvsignore +inittab +livecd.ks.in +livecd-post.sh.in +lvm.conf +Makefile +MANIFEST +p2v.init +README +README.developers +virt-p2v.sh diff --git a/Makefile b/Makefile index f9622fe..86ba446 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ #---------------------------------------------------------------------- # General configuration -VERSION := 0.1 +PACKAGE := virt-p2v +VERSION := 0.2 # i386 images also work on x86-64, so best to stick with i386. ARCH := i386 @@ -19,7 +20,7 @@ BASEREPO := http://download.fedora.redhat.com/pub/fedora/linux/releases/7/Fedora export http_proxy := http://127.0.0.1:3128/ export ftp_proxy := http://127.0.0.1:3128/ -LABEL := virt-p2v-$(VERSION) +LABEL := $(PACKAGE)-$(VERSION) #---------------------------------------------------------------------- @@ -36,6 +37,7 @@ build: checkroot livecd.ks ls -lhtr *.iso livecd.ks: livecd.ks.in livecd-post.sh Makefile + rm -f $@ sed \ -e 's|@BASEREPO@|$(BASEREPO)|g' \ -e 's|@LANG@|$(LANG)|g' \ @@ -43,7 +45,8 @@ livecd.ks: livecd.ks.in livecd-post.sh Makefile -e 's|@TIMEZONE@|$(TIMEZONE)|g' \ < $< | cat - livecd-post.sh > $@ -livecd-post.sh: livecd-post.sh.in p2v.init virt-p2v.sh inittab Makefile +livecd-post.sh: livecd-post.sh.in p2v.init virt-p2v.sh inittab lvm.conf Makefile + rm -f $@ sed \ -e '/@P2V.INIT@/ r p2v.init' \ -e '/@P2V.INIT@/ d' \ @@ -51,6 +54,8 @@ livecd-post.sh: livecd-post.sh.in p2v.init virt-p2v.sh inittab Makefile -e '/@VIRT-P2V.SH@/ d' \ -e '/@INITTAB@/ r inittab' \ -e '/@INITTAB@/ d' \ + -e '/@LVM.CONF@/ r lvm.conf' \ + -e '/@LVM.CONF@/ d' \ < $< > $@ # Run live CD under qemu. @@ -82,4 +87,28 @@ checkroot: clean: rm -f *~ core livecd.ks livecd-post.sh +# Manifest. + +dist: + $(MAKE) check-manifest + rm -rf $(PACKAGE)-$(VERSION) + mkdir $(PACKAGE)-$(VERSION) + tar -cf - -T MANIFEST | tar -C $(PACKAGE)-$(VERSION) -xf - + $(INSTALL) -m 0755 configure $(PACKAGE)-$(VERSION)/ + tar zcf $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE)-$(VERSION) + rm -rf $(PACKAGE)-$(VERSION) + ls -l $(PACKAGE)-$(VERSION).tar.gz + +check-manifest: + @for d in `find -type d -name CVS | grep -v '^\./debian/'`; \ + do \ + b=`dirname $$d`/; \ + awk -F/ '$$1 != "D" {print $$2}' $$d/Entries | \ + sed -e "s|^|$$b|" -e "s|^\./||"; \ + done | sort > .check-manifest; \ + sort MANIFEST > .orig-manifest; \ + diff -u .orig-manifest .check-manifest; rv=$$?; \ + rm -f .orig-manifest .check-manifest; \ + exit $$rv + .PHONY: build boot checkroot \ No newline at end of file diff --git a/README b/README index 30afc68..094a872 100644 --- a/README +++ b/README @@ -8,3 +8,88 @@ Written by: Copyright (C) 2007 Red Hat Inc. + http://et.redhat.com/~rjones/virt-p2v/ + +Binaries +---------------------------------------------------------------------- + +Binaries are available from the website (live CD images which can be +burned directly to a CD and booted on the p2v candidate machine). + +http://et.redhat.com/~rjones/virt-p2v/ + +Building +---------------------------------------------------------------------- + +Requirements: + * livecd-creator (on Fedora the package is 'livecd-tools') + * qemu (only for testing) + +(1) Edit Makefile - there is some general configuration at the + top which you may want to change. + +(2) 'make build' will build an ISO image called virt-p2v-$VERSION.iso + +(3) Burn the image on to a CD using standard tools. + +Booting from USB device +---------------------------------------------------------------------- + +If you wish to boot from a USB keydrive, use the livecd-iso-to-disk +tool: + + livecd-iso-to-disk virt-p2v-$VERSION.iso /dev/sdX1 + +(Replace /dev/sdX1 with the actual USB device). + +In my experience I also had to set up a suitable MBR: + + cat /usr/lib/syslinux/mbr.bin > /dev/sdX + +Running +---------------------------------------------------------------------- + +Boot the candidate machine from the live CD or USB keydrive. + +You will need to have network access to another machine where it will +save the virtual disk images. Ideally that machine will have ssh +access (sshd service running), but there is also a simple network +daemon that you can run on the target machine. Note that the target +machine is usually the Xen host, but it doesn't need to be: you could +copy the images to a staging machine, and later copy them over to the +Xen host. + +Note that the live CD doesn't modify any data on the candidate +machine. + +Answer the questions. There is a tutorial and explanation of some of +the questions on the website which you may wish to follow: +http://et.redhat.com/~rjones/virt-p2v/ + +While the live CD is booted a shell is available on other virtual +consoles. Go to a virtual console using [ALT] [F2] and log in as root +with no password. + +If it works, the result will be disk images for each filesystem from +the candidate machine, which should boot directly or with the minimum +of changes. + +Booting P2V candidate under Xen +---------------------------------------------------------------------- + + +Testing +---------------------------------------------------------------------- + +If you want to test the live CD without actually P2V-ing a real +server, then you can run the ISO directly in qemu. (To do any sort of +realistic testing you will also need an operating system image, +eg. from /var/lib/xen/images, to experiment with). For example: + + $ cp /var/lib/xen/images/rhel5gax32fv.img . + $ make boot HDA=rhel5gax32fv.img + qemu -m 512 -cdrom virt-p2v-0.1.iso -boot d -hda rhel5gax32fv.img + + +Network daemon +---------------------------------------------------------------------- diff --git a/README.developers b/README.developers index 8dd9561..6ba0733 100644 --- a/README.developers +++ b/README.developers @@ -35,6 +35,10 @@ virt-p2v.sh live CD has booted. All the P2V stuff happens from this script. It uses the 'dialog' program to ask questions. +inittab + + Replacement /etc/inittab. + General implementation plan ---------------------------------------------------------------------- @@ -79,5 +83,5 @@ Non-generic virt-p2v The above describes the generic virt-p2v, which asks users questions after boot. It is also possible to build your own live CD, based on -virt-p2v which has various settings compiled in, so it runs -automatically. \ No newline at end of file +virt-p2v, which has various settings compiled in so it runs +automatically. diff --git a/livecd-post.sh.in b/livecd-post.sh.in index 48ca5c5..985dda8 100644 --- a/livecd-post.sh.in +++ b/livecd-post.sh.in @@ -27,6 +27,11 @@ cat > /etc/inittab << '__EOF4123__' @INITTAB@ __EOF4123__ +# Install custom lvm.conf.new (the shell script will rename to +# lvm.conf when the time comes). +cat > /etc/lvm/lvm.conf.new << '__EOF4312__' +@LVM.CONF@ +__EOF4312__ # Turn off firstboot for livecd boots. echo "RUN_FIRSTBOOT=NO" > /etc/sysconfig/firstboot diff --git a/livecd.ks.in b/livecd.ks.in index c69d693..03b9897 100644 --- a/livecd.ks.in +++ b/livecd.ks.in @@ -27,6 +27,7 @@ device-mapper util-linux module-init-tools gzip +kpartx # For remote communications openssh-clients @@ -51,6 +52,7 @@ strace vim-minimal vim-enhanced bind-utils +file diff --git a/lvm.conf b/lvm.conf new file mode 100644 index 0000000..f2abead --- /dev/null +++ b/lvm.conf @@ -0,0 +1,71 @@ +# Heavily customised lvm.conf for live CD. +# $Id$ + +devices { + dir = "/dev" + scan = [ "/dev" ] + + # Set the filter so that only /dev/dm-* (device mapper) devices + # are scanned. + filter = [ "a|^/dev/dm-|", "r/.*/" ] + + cache_dir = "/etc/lvm/cache" + cache_file_prefix = "" + write_cache_state = 1 + + # Allow device-mapper devices to be scanned, and disable + # block-device sanity checking. + types = [ "device-mapper", 16 ] + sysfs_scan = 0 + + md_component_detection = 1 + ignore_suspended_devices = 0 +} + +log { + verbose = 0 + syslog = 1 + overwrite = 0 + level = 0 + indent = 1 + command_names = 0 + prefix = " " +} + +backup { + backup = 1 + backup_dir = "/etc/lvm/backup" + archive = 1 + archive_dir = "/etc/lvm/archive" + retain_min = 10 + retain_days = 30 +} + +shell { + history_size = 100 +} + +global { + umask = 077 + test = 0 + units = "h" + activation = 1 + proc = "/proc" + locking_type = 1 + fallback_to_clustered_locking = 1 + fallback_to_local_locking = 1 + locking_dir = "/var/lock/lvm" +} + +activation { + missing_stripe_filler = "/dev/ioerror" + reserved_stack = 256 + reserved_memory = 8192 + process_priority = -18 + mirror_region_size = 512 + mirror_log_fault_policy = "allocate" + mirror_device_fault_policy = "remove" +} + +# This file must end with a newline + diff --git a/virt-p2v.sh b/virt-p2v.sh index d472578..688664e 100755 --- a/virt-p2v.sh +++ b/virt-p2v.sh @@ -28,22 +28,18 @@ override_remote_transport= # (only if override_remote_transport is 'ssh') override_remote_directory= -# list of local physical devices to examine, separated by spaces, +# 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_physical_devices="" +override_devices_to_send="" -# list of filesystems to send (eg. "sda1 sda2 VolGroup00/LogVol00") -override_filesystems_to_send="" - -# list of root filesystems to examine (eg. "sda3" or +# the root filesystem containing /etc/fstab (eg. "sda3" or # "VolGroup00/LogVol00") -override_root_filesystems="" +override_root_filesystem="" # network configuration # - if empty, ask user -# - if contains a filesystem name (eg. "VolGroup00/LogVol00") try to -# auto-configure network from that +# - "auto" means try to autoconfigure from root filesystem # (XXX needs to contain more ways to override in future) override_network="" @@ -97,6 +93,8 @@ function shell { #---------------------------------------------------------------------- # Device mapper snapshotting. +next_ramdisk=1 + # Create a device-mapper snapshot of a device with ramdisk overlay. # Example: # snapshot sda1 snap @@ -104,6 +102,10 @@ function shell { 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` @@ -111,7 +113,7 @@ function snapshot { --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/ram1 n 64" + --table="0 $sectors snapshot /dev/mapper/${name}_org /dev/ram$i n 64" if [ $? -ne 0 ]; then exit 1; fi } @@ -120,6 +122,8 @@ function snapshot { # 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 } @@ -232,11 +236,9 @@ function search_parts { #---------------------------------------------------------------------- # Network configuration functions. -# `auto_network $fs' mounts /dev/$fs read-only on /mnt/root and then -# tries to configure the network from it. Returns true or false. +# `auto_network $fs' tries to configure the network from the +# root filesystem. Returns true or false. function auto_network { - if ! mount -o ro /dev/$1 /mnt; then return 1; fi - # Make sure this file exists, otherwise Fedora gives a warning. touch /etc/resolv.conf @@ -247,13 +249,11 @@ function auto_network { mv network-scripts network-scripts.saved # Originally I symlinked these, but that causes dhclient to - # keep open /mnt (as its cwd is in network-scripts subdir). + # keep open /mnt/root (as its cwd is in network-scripts subdir). # So now we will copy them recursively instead. - cp -r /mnt/etc/sysconfig/network . - cp -r /mnt/etc/sysconfig/networking . - cp -r /mnt/etc/sysconfig/network-scripts . - # This also means we can umount /mnt early. - umount /mnt + 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=$? @@ -389,9 +389,9 @@ while [ "$state" != "exit" ]; do # Block devices configuration. devices) - if [ -n "$override_physical_devices" ]; then - physical_devices="$override_physical_devices" - state=filesystems + 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 @@ -400,7 +400,7 @@ while [ "$state" != "exit" ]; do deviceslist="" for d in $devices; do - if word_in_list $d $physical_devices; then + if word_in_list $d $devices_to_send; then stat=on else stat=off @@ -412,58 +412,31 @@ while [ "$state" != "exit" ]; do dialog \ --extra-button --extra-label "Back" --nocancel \ --single-quoted \ - --checklist "Pick local disks to examine" 15 50 8 \ + --checklist "Pick disks to send" 15 50 8 \ $deviceslist \ 2> line if [ $? -eq 3 ]; then state=directory else - physical_devices=`cat line` - state=filesystems + devices_to_send=`cat line` + state=root fi fi ;; - filesystems) - if [ -n "$override_filesystems_to_send" ]; then - filesystems_to_send="$override_filesystems_to_send" - state=roots + + # 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 $physical_devices + search_parts $devices_to_send log partitions returned by search_parts: $parts partslist="" - for p in $parts; do - if word_in_list $p $filesystems_to_send; then - stat=on - else - stat=off - fi - gigs=$(($(blockdev --getsize /dev/$p)/2/1024/1024)) - partslist="$partslist $p /dev/$p(${gigs}GB) $stat" - done - - dialog \ - --extra-button --extra-label "Back" --nocancel \ - --single-quoted \ - --checklist "Pick filesystems to send" 15 70 8 \ - $partslist \ - 2> line - if [ $? -eq 3 ]; then state=devices - else - filesystems_to_send=`cat line` - state=roots - fi - fi - ;; - roots) - if [ -n "$override_root_filesystems" ]; then - root_filesystems="$override_root_filesystems" - state=network - else - partslist="" - for r in $filesystems_to_send; do - if word_in_list $r $root_filesystems; then + for r in $parts; do + if word_in_list $r $root_filesystem; then stat=on else stat=off @@ -474,12 +447,12 @@ while [ "$state" != "exit" ]; do dialog \ --extra-button --extra-label "Back" --nocancel \ --single-quoted \ - --checklist "Pick partition(s) containing a root (/) filesystem" 10 70 5 \ + --radiolist "Pick partition containing the root (/) filesystem" 10 70 5 \ $partslist \ 2> line - if [ $? -eq 3 ]; then state=filesystems + if [ $? -eq 3 ]; then state=devices else - root_filesystems=`cat line` + root_filesystem=`cat line` state=network fi fi @@ -491,24 +464,14 @@ while [ "$state" != "exit" ]; do network="$override_network" state=verify else - partslist="" - for r in $root_filesystems; do - if [ "$r" = "$network" ]; then - stat=on - else - stat=off - fi - partslist="$partslist $r Auto-configure $stat" - done - dialog \ --extra-button --extra-label "Back" --nocancel \ --radiolist "Network configuration" 10 70 5 \ - $partslist \ + "auto" "Auto-configure from root filesystem" on \ "ask" "Manual configuration" off \ "sh" "Configure from the shell" off \ 2> line - if [ $? -eq 3 ]; then state=roots + if [ $? -eq 3 ]; then state=root else network=`cat line` state=verify @@ -523,7 +486,7 @@ while [ "$state" != "exit" ]; do else dialog \ --title "Summary" \ - --yesno "Transport: $remote_transport\nRemote host: $remote_host\nRemote port: $remote_port\nRemote directory (ssh only): $remote_directory\nFilesystems to send: $filesystems_to_send\nRoot filesystem(s): $root_filesystems\nNetwork configuration: $network\n\nProceed with these settings?" \ + --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?" \ 23 70 if [ $? -eq 1 ]; then state=transport @@ -541,6 +504,42 @@ 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.new /etc/lvm/lvm.conf +rm -f /etc/lvm/cache/.cache + +# Snapshot the block devices. +for d in $devices_to_send; do + log snapshotting block device /dev/$d ... + + snapshot $d snap_$d + + # The block devices are whole disks. Use kpartx to repartition them. + log running kpartx -a /dev/mapper/snap_$d ... + kpartx -a /dev/mapper/snap_$d +done + +# Rescan for LVs. +log running vgscan +vgscan + +# Mount the root filesystem on /mnt/root. If it's a physical +# device then we want to mount (eg) /dev/mapper/snap_sda1. +# If it's a LVM device (which it probably won't be for Linux because +# Linux doesn't support it) then we can just mount the LVM +# partition. + +log mount $root_filesystem as /mnt/root + +if [ -f /dev/mapper/snap_$root_filesystem ]; then + mount /dev/mapper/snap_$root_filesystem /mnt/root +else + mount /dev/$root_filesystem /mnt/root +fi + # Now see if we can get a network configuration. log network configuration $network @@ -550,10 +549,6 @@ case "$network" in echo echo "Please configure the network from this shell." echo - echo "You can modify any file under /etc (especially /etc/sysconfig)." - echo "No changes are made to the system disks unless you mount them" - echo "and explicitly modify them." - echo echo "When finished, exit with ^D or exit" echo shell @@ -565,7 +560,7 @@ case "$network" in shell ;; - *) + auto) echo "Trying to auto-configure network from /dev/$network ..." echo if ! auto_network "$network"; then @@ -575,20 +570,17 @@ case "$network" in fi esac -# Mount the root filesystem(s) using device-mapper snapshots. -# The snapshots are called snap0, snap1, etc. with the number -# corresponding to its index in $root_filesystems array. - - - - +#---------------------------------------------------------------------- +# Clean up. +umount /mnt/root +drop_snapshot snap # This file must end with a newline -- 1.8.3.1