Enhance AutoInstaller GUI with detailed copy progress and network config improvements

- Add detailed copy system step with real-time rsync output display
- Show current file being copied, transfer statistics, and progress details
- Add small text area for copy progress with monospace font and auto-scroll
- Move network configuration file creation to occur after disk mounting
- This ensures /target/etc/network/interfaces is created on the mounted filesystem
- Update installation progress percentages to accommodate new network config step
- Add copy_progress signal and update_copy_progress method for GUI updates
- Enhanced rsync command with --progress and --stats for detailed output
- Improved error handling for rsync process with proper cleanup

This provides users with detailed feedback during the system copy process
and ensures network configuration files are properly created on target system.
parent cbc92a3b
......@@ -304,6 +304,7 @@ class InstallerWorker(QThread):
step_completed = pyqtSignal(str)
error_occurred = pyqtSignal(str)
finished = pyqtSignal(bool)
copy_progress = pyqtSignal(str)
def __init__(self, config):
super().__init__()
......@@ -333,12 +334,12 @@ class InstallerWorker(QThread):
self.progress_updated.emit(30)
# Step 3: Network Configuration
# Step 3: Network Configuration (moved before mounting)
if self.config.get('configure_network', False):
self.status_updated.emit("Configuring network...")
network_config = self.apply_network_config()
self.config['network_config'] = network_config
self.step_completed.emit("Network configured")
self.status_updated.emit("Preparing network configuration...")
# Just store the config for now, will apply after mounting
self.log("Network configuration will be applied after mounting")
self.step_completed.emit("Network configuration prepared")
else:
self.log("Skipping network configuration")
......@@ -367,28 +368,39 @@ class InstallerWorker(QThread):
self.mount_target(target_disk, target_mount)
self.step_completed.emit("Target mounted")
self.progress_updated.emit(70)
self.progress_updated.emit(65)
# Step 8: Apply Network Configuration (now that target is mounted)
if self.config.get('configure_network', False):
self.status_updated.emit("Applying network configuration to target...")
network_config = self.apply_network_config()
self.config['network_config'] = network_config
self.step_completed.emit("Network configuration applied")
else:
self.log("Skipping network configuration")
self.progress_updated.emit(75)
# Step 8: Copy Live System
# Step 10: Copy Live System
self.status_updated.emit("Copying live system to disk...")
self.copy_live_system(target_mount)
self.step_completed.emit("System copied")
self.progress_updated.emit(80)
self.progress_updated.emit(85)
# Step 9: Configure Target System
# Step 11: Configure Target System
self.status_updated.emit("Configuring target system...")
self.configure_target_system(target_mount)
self.step_completed.emit("System configured")
self.progress_updated.emit(90)
self.progress_updated.emit(95)
# Step 10: Install Bootloader
# Step 12: Install Bootloader
self.status_updated.emit("Installing bootloader...")
self.install_bootloader(target_mount, target_disk)
self.step_completed.emit("Bootloader installed")
self.progress_updated.emit(95)
self.progress_updated.emit(98)
# Post-Install Setup
self.status_updated.emit("Running post-installation setup...")
......@@ -618,10 +630,50 @@ class InstallerWorker(QThread):
self.log("Target mounted")
def copy_live_system(self, target_mount):
# Use rsync via subprocess
cmd = ['rsync', '-av', '--exclude=/proc', '--exclude=/sys', '/', target_mount + '/']
subprocess.run(cmd, check=True)
self.log("System copied")
"""Copy live system with detailed progress output"""
self.log("Starting system copy with detailed progress...")
# Use rsync with progress and verbose output
cmd = [
'rsync', '-av', '--progress', '--stats',
'--exclude=/proc', '--exclude=/sys', '--exclude=/dev',
'--exclude=/tmp', '--exclude=/run', '--exclude=/mnt',
'--exclude=/media', '--exclude=/lost+found',
'--exclude=/lib/live', '--exclude=/cdrom',
'--exclude=/var/cache/apt/archives/*.deb',
'--exclude=/var/log/*', '--exclude=/var/log/auto-installer.log',
'/', target_mount + '/'
]
try:
# Run rsync and capture output
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
universal_newlines=True
)
# Read output line by line and send to GUI
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
# Send progress updates to GUI
self.copy_progress.emit(output.strip())
# Check return code
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, cmd)
self.log("System copy completed successfully")
except subprocess.CalledProcessError as e:
self.log(f"System copy failed with return code {e.returncode}")
raise
def configure_target_system(self, target_mount):
# Bind mounts and chroot commands
......@@ -727,9 +779,19 @@ class AutoInstallerGUI(QMainWindow):
# Log Output
self.log_text = QTextEdit()
self.log_text.setReadOnly(True)
self.log_text.setMaximumHeight(200)
self.log_text.setMaximumHeight(150)
layout.addWidget(self.log_text)
# Copy Progress Output (small text area for rsync details)
copy_group = QGroupBox("Copy Progress Details")
copy_layout = QVBoxLayout(copy_group)
self.copy_progress_text = QTextEdit()
self.copy_progress_text.setReadOnly(True)
self.copy_progress_text.setMaximumHeight(100)
self.copy_progress_text.setFont(QFont("Monospace", 8))
copy_layout.addWidget(self.copy_progress_text)
layout.addWidget(copy_group)
# Exit Button (for fullscreen)
self.exit_button = QPushButton("Exit (Esc)")
self.exit_button.clicked.connect(self.close)
......@@ -795,6 +857,7 @@ class AutoInstallerGUI(QMainWindow):
self.worker.step_completed.connect(self.log_step_completed)
self.worker.error_occurred.connect(self.handle_error)
self.worker.finished.connect(self.installation_finished)
self.worker.copy_progress.connect(self.update_copy_progress)
self.worker.start()
def update_status(self, message):
......@@ -803,6 +866,26 @@ class AutoInstallerGUI(QMainWindow):
def log_step_completed(self, step):
self.log_text.append(f"[COMPLETED] {step}")
def update_copy_progress(self, message):
"""Update the copy progress text area with rsync output"""
# Keep only the last 50 lines to avoid memory issues
current_text = self.copy_progress_text.toPlainText()
lines = current_text.split('\n')
if len(lines) > 45: # Keep some buffer
lines = lines[-45:]
current_text = '\n'.join(lines)
# Append new message
if current_text:
self.copy_progress_text.setPlainText(current_text + '\n' + message)
else:
self.copy_progress_text.setPlainText(message)
# Auto-scroll to bottom
cursor = self.copy_progress_text.textCursor()
cursor.movePosition(cursor.MoveOperation.End)
self.copy_progress_text.setTextCursor(cursor)
def handle_error(self, error):
QMessageBox.critical(self, "Installation Error", error)
self.confirm_button.setEnabled(True)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment