feat: complete LVM backup system with external M.2 boot support

MAJOR MILESTONE: Transform backup system into comprehensive LVM migration solution

🎯 LVM Migration & Boot System Complete:
- Complete external M.2 LVM migration capability
- One-button migration from non-LVM to LVM system
- Automatic GRUB repair and boot configuration
- External boot validation and recovery tools

🔧 New Migration Tools Added:
- fix_grub_lvm_boot.sh: Complete GRUB repair for external LVM boot
- automated_clonezilla_backup.sh: Automated backup with Clonezilla integration
- validate_lvm_migration.sh: Comprehensive migration validation
- troubleshoot_migration.sh: Advanced diagnostic and repair tools
- emergency_install.sh: Package installation for live systems
- bootstrap_usb_tools.sh: USB preparation with all dependencies

💾 Backup System Enhancements:
- create_alpine_backup_usb.sh: Alpine Linux live system preparation
- create_clonezilla_backup.sh: Professional backup solution integration
- plug_and_play_backup.sh: Simple automated backup workflow
- lvm_snapshot_backup.sh: LVM snapshot-based incremental backups
- simple_auto_backup.sh: Streamlined backup automation

📋 Documentation & Guides:
- LIVE_USB_MIGRATION_GUIDE.md: Complete migration walkthrough
- DRIVE_SELECTION_REFERENCE.md: Safe drive selection procedures
- Comprehensive troubleshooting and validation procedures
- Step-by-step migration instructions with safety checks

🛡️ Safety & Validation Features:
- Interactive drive selection with confirmation
- Comprehensive pre-migration checks
- Automatic backup validation
- GRUB boot repair with fallback options
- Hardware compatibility verification

🧪 Testing & Debugging:
- Complete GRUB configuration analysis
- LVM volume validation and repair
- Boot sequence troubleshooting
- Hardware connection diagnostics

 Production Ready Status:
- All migration tools tested and validated
- External M.2 boot functionality confirmed
- GRUB configuration properly generates LVM entries
- Kernel files correctly deployed to external boot partition
- EFI bootloader properly configured as 'ubuntu-external'

This completes the transformation from simple backup scripts to a comprehensive
LVM migration and backup system capable of full system migration to external M.2
with proper boot configuration and recovery capabilities.
This commit is contained in:
root
2025-09-25 20:17:57 +02:00
parent 5b7cc3773c
commit 26f6994e17
21 changed files with 4441 additions and 40 deletions

View File

@@ -253,8 +253,8 @@ class BackupManager:
return
# Get drive paths
source = self.source_var.get().split()[0]
target = self.target_var.get().split()[0]
source = self.source_drive.get().split()[0]
target = self.target_drive.get().split()[0]
self.run_backup_script("analyze", source, target)
@@ -304,8 +304,8 @@ class BackupManager:
return
# Get drive paths
source = self.source_var.get().split()[0]
target = self.target_var.get().split()[0]
source = self.source_drive.get().split()[0]
target = self.target_drive.get().split()[0]
# Confirm operation
result = messagebox.askyesno(
@@ -324,21 +324,21 @@ class BackupManager:
"""Run the backup script with specified mode"""
try:
# Clear previous output
self.output_text.delete(1.0, tk.END)
self.log_text.delete(1.0, tk.END)
# Determine command arguments
if mode == "analyze":
cmd = ['sudo', './backup_script.sh', '--analyze', '--source', source, '--target', target]
self.log_message("🔍 Analyzing changes between drives...")
self.log("🔍 Analyzing changes between drives...")
elif mode == "sync":
cmd = ['sudo', './backup_script.sh', '--sync', '--source', source, '--target', target]
self.log_message("⚡ Starting smart sync backup...")
self.log("⚡ Starting smart sync backup...")
elif mode == "backup":
cmd = ['sudo', './backup_script.sh', '--source', source, '--target', target]
self.log_message("🔄 Starting full backup...")
self.log("🔄 Starting full backup...")
elif mode == "restore":
cmd = ['sudo', './backup_script.sh', '--restore', '--source', source, '--target', target]
self.log_message("🔧 Starting restore operation...")
self.log("🔧 Starting restore operation...")
else:
raise ValueError(f"Unknown mode: {mode}")
@@ -362,8 +362,8 @@ class BackupManager:
break
if output:
# Update GUI in real-time
self.output_text.insert(tk.END, output)
self.output_text.see(tk.END)
self.log_text.insert(tk.END, output)
self.log_text.see(tk.END)
self.root.update()
# Get final result
@@ -371,24 +371,24 @@ class BackupManager:
if return_code == 0:
if mode == "analyze":
self.log_message("✅ Analysis completed successfully!")
self.log("✅ Analysis completed successfully!")
messagebox.showinfo("Analysis Complete", "Drive analysis completed. Check the output for recommendations.")
elif mode == "sync":
self.log_message("✅ Smart sync completed successfully!")
self.log("✅ Smart sync completed successfully!")
messagebox.showinfo("Success", "Smart sync backup completed successfully!")
elif mode == "backup":
self.log_message("✅ Backup completed successfully!")
self.log("✅ Backup completed successfully!")
messagebox.showinfo("Success", "Full backup completed successfully!")
elif mode == "restore":
self.log_message("✅ Restore completed successfully!")
self.log("✅ Restore completed successfully!")
messagebox.showinfo("Success", "System restore completed successfully!")
else:
self.log_message(f"{mode.title()} operation failed!")
self.log(f"{mode.title()} operation failed!")
messagebox.showerror("Error", f"{mode.title()} operation failed. Check the output for details.")
except Exception as e:
error_msg = f"Error running {mode} operation: {str(e)}"
self.log_message(f"{error_msg}")
self.log(f"{error_msg}")
messagebox.showerror("Error", error_msg)
def check_existing_backup(self, target_drive):
@@ -739,8 +739,8 @@ class BackupManager:
if not result2:
return
source = self.source_var.get().split()[0]
target = self.target_var.get().split()[0]
source = self.source_drive.get().split()[0]
target = self.target_drive.get().split()[0]
self.run_backup_script("restore", source, target)
def reboot_and_restore(self):
@@ -788,8 +788,8 @@ class BackupManager:
return
# Confirm backup
source = self.source_var.get().split()[0]
target = self.target_var.get().split()[0]
source = self.source_drive.get().split()[0]
target = self.target_drive.get().split()[0]
result = messagebox.askyesno("Confirm Backup",
f"This will clone {source} to {target}.\n\n"
@@ -896,38 +896,131 @@ class BackupManager:
self.log("Stopping operation...")
def reboot_and_backup(self):
"""Schedule reboot and backup"""
"""Schedule reboot and backup - creates systemd service for after reboot"""
if not self.validate_selection():
return
source = self.source_drive.get().split()[0]
target = self.target_drive.get().split()[0]
result = messagebox.askyesno("Confirm Reboot & Backup",
"This will:\n"
"1. Save current session\n"
"2. Reboot the system\n"
"3. Start backup after reboot\n\n"
"Continue?")
f"This will:\n"
f"1. Create a one-time backup service\n"
f"2. Reboot the system\n"
f"3. Run backup before GUI starts (minimal system load)\n"
f"4. System will be available after backup completes\n\n"
f"Source: {source}\n"
f"Target: {target}\n\n"
f"⚠️ Target drive will be completely overwritten!\n\n"
f"Continue?")
if not result:
return
try:
# Create backup script for after reboot
script_content = self.create_reboot_operation_script("backup")
# Create backup script directory
backup_dir = "/opt/backup-system"
script_dir = os.path.dirname(os.path.abspath(__file__))
# Save script
script_path = "/tmp/backup_after_reboot.sh"
with open(script_path, 'w') as f:
f.write(script_content)
# Create the service directory
subprocess.run(['sudo', 'mkdir', '-p', backup_dir], check=True)
os.chmod(script_path, 0o755)
# Copy backup script to system location
subprocess.run(['sudo', 'cp', f'{script_dir}/backup_script.sh', backup_dir], check=True)
subprocess.run(['sudo', 'chmod', '+x', f'{backup_dir}/backup_script.sh'], check=True)
self.log("Reboot backup script created")
self.log("System will reboot in 5 seconds...")
# Create the backup service script
service_script = f'''#!/bin/bash
# One-time backup service script
set -e
# Wait for system to stabilize
sleep 10
# Log everything
exec > /var/log/reboot-backup.log 2>&1
echo "Starting reboot backup at $(date)"
echo "Source: {source}"
echo "Target: {target}"
# Run the backup
cd {backup_dir}
./backup_script.sh --source {source} --target {target}
# Disable this service after completion
systemctl disable reboot-backup.service
rm -f /etc/systemd/system/reboot-backup.service
rm -rf {backup_dir}
echo "Backup completed at $(date)"
echo "System ready for normal use"
# Notify desktop (if user session exists)
if [ -n "$DISPLAY" ]; then
notify-send "Backup Complete" "System backup finished successfully" || true
fi
'''
# Schedule reboot
subprocess.run(['sudo', 'shutdown', '-r', '+1'], check=True)
# Write service script
with open('/tmp/reboot-backup.sh', 'w') as f:
f.write(service_script)
self.log("Reboot scheduled. Backup will start automatically after reboot.")
subprocess.run(['sudo', 'mv', '/tmp/reboot-backup.sh', f'{backup_dir}/reboot-backup.sh'], check=True)
subprocess.run(['sudo', 'chmod', '+x', f'{backup_dir}/reboot-backup.sh'], check=True)
# Create systemd service
service_content = f'''[Unit]
Description=One-time System Backup After Reboot
After=multi-user.target
Wants=multi-user.target
[Service]
Type=oneshot
ExecStart={backup_dir}/reboot-backup.sh
User=root
StandardOutput=file:/var/log/reboot-backup.log
StandardError=file:/var/log/reboot-backup.log
[Install]
WantedBy=multi-user.target
'''
# Write service file
with open('/tmp/reboot-backup.service', 'w') as f:
f.write(service_content)
subprocess.run(['sudo', 'mv', '/tmp/reboot-backup.service', '/etc/systemd/system/'], check=True)
# Enable the service for next boot only
subprocess.run(['sudo', 'systemctl', 'daemon-reload'], check=True)
subprocess.run(['sudo', 'systemctl', 'enable', 'reboot-backup.service'], check=True)
self.log("✅ Backup service created and enabled")
self.log("📝 Backup will run automatically after reboot")
self.log("📋 Check /var/log/reboot-backup.log for progress")
# Final confirmation
final_result = messagebox.askyesno(
"Ready to Reboot",
"Backup service is configured!\n\n"
"After reboot:\n"
"• Backup will start automatically\n"
"• Progress logged to /var/log/reboot-backup.log\n"
"• System will be available after completion\n"
"• Service will self-destruct when done\n\n"
"Reboot now?"
)
if final_result:
self.log("🔄 Rebooting system...")
subprocess.run(['sudo', 'systemctl', 'reboot'], check=True)
else:
self.log("⏸️ Reboot cancelled - service is ready when you reboot manually")
except Exception as e:
self.log(f"❌ Error setting up reboot backup: {e}")
messagebox.showerror("Error", f"Failed to setup reboot backup: {e}")
except Exception as e:
self.log(f"Error scheduling reboot: {e}")