- Removed 40+ broken/messy scripts, moved to old_scripts/ - Created lvm_block_backup.sh - proper block-level LVM snapshot backup - Uses dd for block-level cloning instead of file-level rsync - Successfully tested: 462GB backup in 33 minutes - Creates exact, bootable clone of internal drive to external drive - Proper LVM snapshot management with cleanup - Clear documentation in README_BACKUP.md - Clean, minimal solution that actually works
552 lines
18 KiB
Bash
Executable File
552 lines
18 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Improved LVM Migration Script
|
|
# Fixes the boot issues from the previous failed LVM migration
|
|
# Properly handles LUKS + LVM combination with robust boot configuration
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Configuration variables
|
|
INTERNAL_DRIVE=""
|
|
EXTERNAL_DRIVE=""
|
|
VG_NAME="system-vg"
|
|
ROOT_LV="root"
|
|
HOME_LV="home"
|
|
SWAP_LV="swap"
|
|
BOOT_LV="boot"
|
|
|
|
# Work directory
|
|
WORK_DIR="/mnt/lvm_migration"
|
|
|
|
# Detected partitions and info
|
|
declare -A INTERNAL_PARTITIONS
|
|
declare -A PARTITION_FILESYSTEMS
|
|
declare -A PARTITION_SIZES
|
|
|
|
log() {
|
|
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}[ERROR]${NC} $1" >&2
|
|
exit 1
|
|
}
|
|
|
|
warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
confirm_action() {
|
|
echo -e "${YELLOW}$1${NC}"
|
|
read -p "Do you want to continue? [y/N] " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
error "Operation aborted by user"
|
|
fi
|
|
}
|
|
|
|
detect_drives() {
|
|
log "Detecting available drives..."
|
|
|
|
local all_drives=($(lsblk -dpno NAME,TYPE | grep "disk" | awk '{print $1}'))
|
|
local drives=()
|
|
|
|
# Filter out the USB stick we're running from
|
|
for drive in "${all_drives[@]}"; do
|
|
if mount | grep -q "$drive" && mount | grep -q "/lib/live\|overlay\|/media.*live"; then
|
|
log "Excluding live USB drive: $drive"
|
|
continue
|
|
fi
|
|
drives+=("$drive")
|
|
done
|
|
|
|
if [ ${#drives[@]} -lt 2 ]; then
|
|
error "Need at least 2 drives for migration. Found only ${#drives[@]} suitable drives"
|
|
fi
|
|
|
|
echo "Available drives:"
|
|
for i in "${!drives[@]}"; do
|
|
local drive="${drives[$i]}"
|
|
local info=$(lsblk -dpno SIZE,MODEL "$drive" | xargs)
|
|
echo "$((i+1)). $drive - $info"
|
|
lsblk "$drive" | tail -n +2 | sed 's/^/ /'
|
|
echo
|
|
done
|
|
|
|
# Auto-detect with user confirmation
|
|
local suggested_internal=""
|
|
local suggested_external=""
|
|
|
|
# Prefer NVMe for internal, USB for external
|
|
for drive in "${drives[@]}"; do
|
|
if [[ "$drive" == *"nvme"* ]]; then
|
|
suggested_internal="$drive"
|
|
break
|
|
fi
|
|
done
|
|
|
|
for drive in "${drives[@]}"; do
|
|
if [ "$drive" != "$suggested_internal" ]; then
|
|
if udevadm info --query=property --name="$drive" 2>/dev/null | grep -q "ID_BUS=usb"; then
|
|
suggested_external="$drive"
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if [ -n "$suggested_internal" ] && [ -n "$suggested_external" ]; then
|
|
echo "Suggested configuration:"
|
|
echo " Internal (source): $suggested_internal"
|
|
echo " External (LVM target): $suggested_external"
|
|
read -p "Use this configuration? [Y/n]: " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
|
INTERNAL_DRIVE="$suggested_internal"
|
|
EXTERNAL_DRIVE="$suggested_external"
|
|
fi
|
|
fi
|
|
|
|
# Manual selection if needed
|
|
if [ -z "$INTERNAL_DRIVE" ]; then
|
|
read -p "Select INTERNAL drive number: " choice
|
|
INTERNAL_DRIVE="${drives[$((choice-1))]}"
|
|
fi
|
|
|
|
if [ -z "$EXTERNAL_DRIVE" ]; then
|
|
read -p "Select EXTERNAL drive number: " choice
|
|
EXTERNAL_DRIVE="${drives[$((choice-1))]}"
|
|
fi
|
|
|
|
# Safety checks
|
|
if [ "$INTERNAL_DRIVE" = "$EXTERNAL_DRIVE" ]; then
|
|
error "Internal and external drives cannot be the same!"
|
|
fi
|
|
|
|
local external_size_bytes=$(lsblk -bno SIZE "$EXTERNAL_DRIVE")
|
|
local internal_size_bytes=$(lsblk -bno SIZE "$INTERNAL_DRIVE")
|
|
|
|
if [ "$external_size_bytes" -lt "$internal_size_bytes" ]; then
|
|
error "External drive is smaller than internal drive"
|
|
fi
|
|
|
|
echo
|
|
echo "Final configuration:"
|
|
echo " Internal (source): $INTERNAL_DRIVE"
|
|
echo " External (LVM target): $EXTERNAL_DRIVE"
|
|
|
|
# Final safety confirmation
|
|
echo
|
|
echo -e "${RED}⚠️ FINAL SAFETY CHECK ⚠️${NC}"
|
|
echo "This will COMPLETELY WIPE: $EXTERNAL_DRIVE"
|
|
echo "Current partitions that will be DESTROYED:"
|
|
lsblk "$EXTERNAL_DRIVE"
|
|
echo
|
|
read -p "Type 'MIGRATE' to confirm LVM migration: " confirmation
|
|
if [ "$confirmation" != "MIGRATE" ]; then
|
|
error "Migration cancelled by user"
|
|
fi
|
|
|
|
success "Drive selection completed"
|
|
}
|
|
|
|
analyze_source_system() {
|
|
log "Analyzing source system..."
|
|
|
|
local partitions=($(lsblk -pno NAME "$INTERNAL_DRIVE" | grep -v "^$INTERNAL_DRIVE$"))
|
|
|
|
echo "Source drive partitions:"
|
|
for part in "${partitions[@]}"; do
|
|
local size=$(lsblk -no SIZE "$part")
|
|
local fstype=$(lsblk -no FSTYPE "$part")
|
|
local label=$(lsblk -no LABEL "$part")
|
|
local mountpoint=$(lsblk -no MOUNTPOINT "$part")
|
|
|
|
echo " $part: $size, $fstype, ${label:-'no label'}"
|
|
|
|
PARTITION_FILESYSTEMS["$part"]="$fstype"
|
|
PARTITION_SIZES["$part"]="$size"
|
|
|
|
# Identify partitions
|
|
if [[ "$fstype" == "vfat" ]] && [[ "$part" == *"1" ]] || [[ "$part" == *"2" ]]; then
|
|
INTERNAL_PARTITIONS["efi"]="$part"
|
|
elif [[ "$mountpoint" == "/" ]] || [[ "$label" == "root"* ]] || [[ "$fstype" == "ext4" && "$part" == *"1" ]]; then
|
|
INTERNAL_PARTITIONS["root"]="$part"
|
|
elif [[ "$mountpoint" == "/home" ]] || [[ "$label" == "home"* ]]; then
|
|
INTERNAL_PARTITIONS["home"]="$part"
|
|
elif [[ "$fstype" == "crypto_LUKS" ]]; then
|
|
# Encrypted partition - likely home
|
|
INTERNAL_PARTITIONS["encrypted_home"]="$part"
|
|
fi
|
|
done
|
|
|
|
success "Source system analysis completed"
|
|
}
|
|
|
|
check_prerequisites() {
|
|
log "Checking prerequisites and installing required tools..."
|
|
|
|
# Check if running from live system
|
|
if ! df / | grep -q "loop\|overlay\|tmpfs"; then
|
|
warning "Not running from live system - this may cause issues"
|
|
confirm_action "Continue anyway?"
|
|
fi
|
|
|
|
# Install/update required packages
|
|
log "Installing required packages..."
|
|
apt update >/dev/null 2>&1
|
|
apt install -y lvm2 cryptsetup rsync parted pv grub-efi-amd64 grub-common \
|
|
e2fsprogs dosfstools bc util-linux initramfs-tools \
|
|
efibootmgr os-prober >/dev/null 2>&1
|
|
|
|
# Ensure LVM2 is properly loaded
|
|
modprobe dm-mod
|
|
modprobe dm-crypt
|
|
vgchange -ay 2>/dev/null || true
|
|
|
|
success "Prerequisites installed"
|
|
}
|
|
|
|
create_lvm_layout() {
|
|
log "Creating LVM layout on external drive..."
|
|
|
|
# Calculate sizes based on source
|
|
local root_size="70G"
|
|
local home_size="100G"
|
|
local swap_size="8G"
|
|
local boot_size="2G"
|
|
|
|
# Adjust based on available space
|
|
local total_space_gb=$(lsblk -bno SIZE "$EXTERNAL_DRIVE" | awk '{print int($1/1024/1024/1024)}')
|
|
if [ "$total_space_gb" -gt 500 ]; then
|
|
home_size="200G"
|
|
root_size="100G"
|
|
fi
|
|
|
|
log "LVM sizes: Root=$root_size, Home=$home_size, Swap=$swap_size, Boot=$boot_size"
|
|
|
|
# Wipe and create partition table
|
|
wipefs -a "$EXTERNAL_DRIVE"
|
|
parted -s "$EXTERNAL_DRIVE" mklabel gpt
|
|
|
|
# Create EFI partition (512MB)
|
|
parted -s "$EXTERNAL_DRIVE" mkpart primary fat32 1MiB 513MiB
|
|
parted -s "$EXTERNAL_DRIVE" set 1 boot on
|
|
parted -s "$EXTERNAL_DRIVE" set 1 esp on
|
|
|
|
# Create LVM partition (rest of disk)
|
|
parted -s "$EXTERNAL_DRIVE" mkpart primary 513MiB 100%
|
|
parted -s "$EXTERNAL_DRIVE" set 2 lvm on
|
|
|
|
# Wait for partitions
|
|
sleep 3
|
|
partprobe "$EXTERNAL_DRIVE"
|
|
sleep 2
|
|
|
|
# Verify partitions exist
|
|
if [ ! -b "${EXTERNAL_DRIVE}1" ] || [ ! -b "${EXTERNAL_DRIVE}2" ]; then
|
|
error "Partitions not created properly"
|
|
fi
|
|
|
|
# Create filesystems
|
|
mkfs.fat -F32 "${EXTERNAL_DRIVE}1" || error "Failed to create EFI filesystem"
|
|
|
|
# Setup LVM
|
|
pvcreate "${EXTERNAL_DRIVE}2" || error "Failed to create physical volume"
|
|
vgcreate "$VG_NAME" "${EXTERNAL_DRIVE}2" || error "Failed to create volume group"
|
|
|
|
# Create logical volumes
|
|
lvcreate -L "$ROOT_SIZE" -n "$ROOT_LV" "$VG_NAME" || error "Failed to create root LV"
|
|
lvcreate -L "$HOME_SIZE" -n "$HOME_LV" "$VG_NAME" || error "Failed to create home LV"
|
|
lvcreate -L "$SWAP_SIZE" -n "$SWAP_LV" "$VG_NAME" || error "Failed to create swap LV"
|
|
lvcreate -L "$BOOT_SIZE" -n "$BOOT_LV" "$VG_NAME" || error "Failed to create boot LV"
|
|
|
|
# Create filesystems on LVM volumes
|
|
mkfs.ext4 -L "root" "/dev/$VG_NAME/$ROOT_LV" || error "Failed to create root filesystem"
|
|
mkfs.ext4 -L "home" "/dev/$VG_NAME/$HOME_LV" || error "Failed to create home filesystem"
|
|
mkfs.ext4 -L "boot" "/dev/$VG_NAME/$BOOT_LV" || error "Failed to create boot filesystem"
|
|
mkswap -L "swap" "/dev/$VG_NAME/$SWAP_LV" || error "Failed to create swap"
|
|
|
|
success "LVM layout created successfully"
|
|
}
|
|
|
|
handle_encrypted_partitions() {
|
|
log "Handling encrypted partitions..."
|
|
|
|
for part_name in "${!INTERNAL_PARTITIONS[@]}"; do
|
|
local part_device="${INTERNAL_PARTITIONS[$part_name]}"
|
|
local fstype="${PARTITION_FILESYSTEMS[$part_device]}"
|
|
|
|
if [[ "$fstype" == "crypto_LUKS" ]]; then
|
|
log "Found encrypted partition: $part_device"
|
|
local crypt_name="migration_${part_name}"
|
|
|
|
echo "Please enter password for encrypted partition ($part_device):"
|
|
if cryptsetup open "$part_device" "$crypt_name"; then
|
|
success "Unlocked $part_device as /dev/mapper/$crypt_name"
|
|
INTERNAL_PARTITIONS["$part_name"]="/dev/mapper/$crypt_name"
|
|
|
|
# Update filesystem type
|
|
local decrypted_fs=$(lsblk -no FSTYPE "/dev/mapper/$crypt_name")
|
|
PARTITION_FILESYSTEMS["/dev/mapper/$crypt_name"]="$decrypted_fs"
|
|
else
|
|
error "Failed to unlock encrypted partition"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
success "Encrypted partitions handled"
|
|
}
|
|
|
|
mount_filesystems() {
|
|
log "Mounting filesystems..."
|
|
|
|
mkdir -p "$WORK_DIR"/{internal_root,internal_home,external_root,external_home,external_boot}
|
|
|
|
# Mount internal filesystems
|
|
if [ -n "${INTERNAL_PARTITIONS[root]}" ]; then
|
|
mount "${INTERNAL_PARTITIONS[root]}" "$WORK_DIR/internal_root"
|
|
fi
|
|
|
|
if [ -n "${INTERNAL_PARTITIONS[home]}" ]; then
|
|
mount "${INTERNAL_PARTITIONS[home]}" "$WORK_DIR/internal_home"
|
|
elif [ -n "${INTERNAL_PARTITIONS[encrypted_home]}" ]; then
|
|
mount "${INTERNAL_PARTITIONS[encrypted_home]}" "$WORK_DIR/internal_home"
|
|
fi
|
|
|
|
# Mount external LVM filesystems
|
|
mount "/dev/$VG_NAME/$ROOT_LV" "$WORK_DIR/external_root"
|
|
mount "/dev/$VG_NAME/$HOME_LV" "$WORK_DIR/external_home"
|
|
mount "/dev/$VG_NAME/$BOOT_LV" "$WORK_DIR/external_boot"
|
|
|
|
# Mount EFI
|
|
mkdir -p "$WORK_DIR/external_root/boot/efi"
|
|
mount "${EXTERNAL_DRIVE}1" "$WORK_DIR/external_root/boot/efi"
|
|
|
|
success "Filesystems mounted"
|
|
}
|
|
|
|
copy_system_data() {
|
|
log "Copying system data..."
|
|
|
|
# Copy root filesystem
|
|
if [ -d "$WORK_DIR/internal_root" ]; then
|
|
log "Copying root filesystem..."
|
|
rsync -avxHAX --progress \
|
|
--exclude=/home/* --exclude=/proc/* --exclude=/sys/* \
|
|
--exclude=/dev/* --exclude=/run/* --exclude=/tmp/* \
|
|
--exclude=/var/tmp/* --exclude=/mnt/* --exclude=/media/* \
|
|
"$WORK_DIR/internal_root/" "$WORK_DIR/external_root/"
|
|
fi
|
|
|
|
# Copy home filesystem
|
|
if [ -d "$WORK_DIR/internal_home" ]; then
|
|
log "Copying home filesystem..."
|
|
rsync -avxHAX --progress "$WORK_DIR/internal_home/" "$WORK_DIR/external_home/"
|
|
elif [ -d "$WORK_DIR/internal_root/home" ]; then
|
|
log "Copying /home from root filesystem..."
|
|
rsync -avxHAX --progress "$WORK_DIR/internal_root/home/" "$WORK_DIR/external_home/"
|
|
fi
|
|
|
|
# Copy boot files
|
|
if [ -d "$WORK_DIR/internal_root/boot" ]; then
|
|
log "Copying boot files..."
|
|
rsync -avxHAX --progress \
|
|
--exclude=/boot/efi/* \
|
|
"$WORK_DIR/internal_root/boot/" "$WORK_DIR/external_boot/"
|
|
fi
|
|
|
|
success "System data copied"
|
|
}
|
|
|
|
configure_lvm_system() {
|
|
log "Configuring LVM system..."
|
|
|
|
# Get UUIDs
|
|
local root_uuid=$(blkid -s UUID -o value "/dev/$VG_NAME/$ROOT_LV")
|
|
local home_uuid=$(blkid -s UUID -o value "/dev/$VG_NAME/$HOME_LV")
|
|
local boot_uuid=$(blkid -s UUID -o value "/dev/$VG_NAME/$BOOT_LV")
|
|
local efi_uuid=$(blkid -s UUID -o value "${EXTERNAL_DRIVE}1")
|
|
local swap_uuid=$(blkid -s UUID -o value "/dev/$VG_NAME/$SWAP_LV")
|
|
|
|
# Create new fstab
|
|
cat > "$WORK_DIR/external_root/etc/fstab" << EOF
|
|
# /etc/fstab: static file system information for LVM system
|
|
UUID=$root_uuid / ext4 defaults 0 1
|
|
UUID=$efi_uuid /boot/efi vfat defaults 0 2
|
|
UUID=$boot_uuid /boot ext4 defaults 0 2
|
|
UUID=$home_uuid /home ext4 defaults 0 2
|
|
UUID=$swap_uuid none swap sw 0 0
|
|
tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
|
|
EOF
|
|
|
|
# Configure LVM in initramfs
|
|
echo "$VG_NAME" >> "$WORK_DIR/external_root/etc/initramfs-tools/conf.d/lvm"
|
|
echo "BOOT=local" >> "$WORK_DIR/external_root/etc/initramfs-tools/conf.d/resume"
|
|
|
|
# Ensure LVM modules are included
|
|
cat > "$WORK_DIR/external_root/etc/initramfs-tools/modules" << EOF
|
|
# LVM modules
|
|
dm-mod
|
|
dm-crypt
|
|
dm-snapshot
|
|
EOF
|
|
|
|
# Update GRUB configuration for LVM
|
|
sed -i 's/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/' "$WORK_DIR/external_root/etc/default/grub"
|
|
echo 'GRUB_PRELOAD_MODULES="lvm"' >> "$WORK_DIR/external_root/etc/default/grub"
|
|
|
|
success "LVM system configured"
|
|
}
|
|
|
|
install_bootloader() {
|
|
log "Installing bootloader with LVM support..."
|
|
|
|
# Bind mount necessary filesystems
|
|
mount --bind /dev "$WORK_DIR/external_root/dev"
|
|
mount --bind /proc "$WORK_DIR/external_root/proc"
|
|
mount --bind /sys "$WORK_DIR/external_root/sys"
|
|
mount --bind /run "$WORK_DIR/external_root/run"
|
|
|
|
# Install and configure bootloader in chroot
|
|
chroot "$WORK_DIR/external_root" /bin/bash -c "
|
|
# Ensure LVM is available
|
|
vgscan
|
|
vgchange -ay
|
|
|
|
# Update initramfs with LVM support
|
|
echo 'MODULES=dep' > /etc/initramfs-tools/initramfs.conf
|
|
echo 'BOOT=local' >> /etc/initramfs-tools/initramfs.conf
|
|
update-initramfs -u -k all
|
|
|
|
# Install GRUB with LVM support
|
|
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck $EXTERNAL_DRIVE
|
|
|
|
# Update GRUB configuration
|
|
update-grub
|
|
|
|
# Verify LVM tools are available
|
|
which lvm && echo 'LVM tools available'
|
|
ls -la /boot/initrd.img-* | head -1
|
|
"
|
|
|
|
# Unmount bind mounts
|
|
umount "$WORK_DIR/external_root/dev" 2>/dev/null || true
|
|
umount "$WORK_DIR/external_root/proc" 2>/dev/null || true
|
|
umount "$WORK_DIR/external_root/sys" 2>/dev/null || true
|
|
umount "$WORK_DIR/external_root/run" 2>/dev/null || true
|
|
|
|
success "Bootloader installed with LVM support"
|
|
}
|
|
|
|
verify_lvm_boot() {
|
|
log "Verifying LVM boot configuration..."
|
|
|
|
# Check if initramfs contains LVM modules
|
|
local initrd_file=$(ls "$WORK_DIR/external_boot/initrd.img-"* 2>/dev/null | head -1)
|
|
if [ -n "$initrd_file" ]; then
|
|
if lsinitramfs "$initrd_file" | grep -q "dm-mod\|lvm"; then
|
|
success "Initramfs contains LVM modules"
|
|
else
|
|
warning "Initramfs may be missing LVM modules"
|
|
fi
|
|
fi
|
|
|
|
# Check GRUB configuration
|
|
if grep -q "lvm" "$WORK_DIR/external_boot/grub/grub.cfg"; then
|
|
success "GRUB configuration includes LVM support"
|
|
else
|
|
warning "GRUB configuration may not have proper LVM support"
|
|
fi
|
|
|
|
# Check fstab
|
|
if grep -q "/dev/$VG_NAME" "$WORK_DIR/external_root/etc/fstab"; then
|
|
success "fstab configured for LVM"
|
|
else
|
|
warning "fstab configuration issue"
|
|
fi
|
|
|
|
success "LVM boot verification completed"
|
|
}
|
|
|
|
cleanup() {
|
|
log "Cleaning up..."
|
|
|
|
# Unmount filesystems
|
|
umount "$WORK_DIR/external_root/boot/efi" 2>/dev/null || true
|
|
umount "$WORK_DIR/external_root" 2>/dev/null || true
|
|
umount "$WORK_DIR/external_home" 2>/dev/null || true
|
|
umount "$WORK_DIR/external_boot" 2>/dev/null || true
|
|
umount "$WORK_DIR/internal_root" 2>/dev/null || true
|
|
umount "$WORK_DIR/internal_home" 2>/dev/null || true
|
|
|
|
# Close encrypted partitions
|
|
for mapper in /dev/mapper/migration_*; do
|
|
if [ -b "$mapper" ]; then
|
|
cryptsetup close "$(basename "$mapper")" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
success "Cleanup completed"
|
|
}
|
|
|
|
main() {
|
|
echo -e "${GREEN}=== Improved LVM Migration Script ===${NC}"
|
|
echo "This script migrates your system to LVM with proper boot configuration"
|
|
echo "Fixes the issues from the previous failed migration"
|
|
echo
|
|
|
|
check_prerequisites
|
|
detect_drives
|
|
analyze_source_system
|
|
|
|
echo
|
|
echo "Migration Summary:"
|
|
echo " Source: $INTERNAL_DRIVE (current system)"
|
|
echo " Target: $EXTERNAL_DRIVE (new LVM system)"
|
|
echo " VG Name: $VG_NAME"
|
|
echo
|
|
|
|
confirm_action "Start LVM migration?"
|
|
|
|
create_lvm_layout
|
|
handle_encrypted_partitions
|
|
mount_filesystems
|
|
copy_system_data
|
|
configure_lvm_system
|
|
install_bootloader
|
|
verify_lvm_boot
|
|
cleanup
|
|
|
|
success "LVM migration completed successfully!"
|
|
echo
|
|
echo -e "${GREEN}=== MIGRATION COMPLETE ===${NC}"
|
|
echo "✅ System migrated to LVM with proper boot support"
|
|
echo "✅ Initramfs configured with LVM modules"
|
|
echo "✅ GRUB installed with LVM support"
|
|
echo "✅ Boot configuration verified"
|
|
echo
|
|
echo -e "${BLUE}Next steps:${NC}"
|
|
echo "1. Reboot system"
|
|
echo "2. Set external drive as first boot device in BIOS"
|
|
echo "3. Boot should work without reset loops"
|
|
echo "4. System will ask for any encryption passwords as normal"
|
|
echo
|
|
echo -e "${YELLOW}🎉 Improved LVM migration completed!${NC}"
|
|
echo "This version fixes the boot issues from the previous attempt."
|
|
}
|
|
|
|
# Trap for cleanup
|
|
trap cleanup EXIT
|
|
|
|
main "$@" |