added functionality to delete existing partitions before reinstall
Some checks failed
Build / build (push) Failing after 4m53s
Some checks failed
Build / build (push) Failing after 4m53s
This commit is contained in:
@@ -145,28 +145,71 @@ func (m InstallModel) saveConfigurationFiles() error {
|
||||
func (m InstallModel) partitionDisk() error {
|
||||
disk := m.config.Disk
|
||||
|
||||
m.updateProgress(m.currentStep, "Clearing existing partition table...")
|
||||
|
||||
// Ensure the disk device exists
|
||||
if _, err := os.Stat(disk); os.IsNotExist(err) {
|
||||
return fmt.Errorf("disk device %s does not exist", disk)
|
||||
}
|
||||
|
||||
// Kill all processes using the disk
|
||||
killCmd := exec.Command("fuser", "-k", disk)
|
||||
killCmd.Run() // Ignore errors as the device might not be in use
|
||||
|
||||
// Wait a moment for processes to terminate
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
// Wipe filesystem signatures
|
||||
wipeDisk := exec.Command("wipefs", "-af", disk)
|
||||
if err := wipeDisk.Run(); err != nil {
|
||||
return err
|
||||
if output, err := wipeDisk.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to wipe filesystem signatures: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
sgdisk := exec.Command("sgdisk", "-Z", disk)
|
||||
if err := sgdisk.Run(); err != nil {
|
||||
return err
|
||||
// Zap (clear) the GPT and MBR partition table
|
||||
sgdiskZap := exec.Command("sgdisk", "--zap-all", disk)
|
||||
if output, err := sgdiskZap.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to zap partition table: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
createEFI := exec.Command("sgdisk", "-n", "1:0:+512M", "-t", "1:ef00", disk)
|
||||
if err := createEFI.Run(); err != nil {
|
||||
return err
|
||||
// Clear with dd for additional safety
|
||||
ddClear := exec.Command("dd", "if=/dev/zero", "of="+disk, "bs=1M", "count=100", "status=none")
|
||||
if output, err := ddClear.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to clear disk header: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
createRoot := exec.Command("sgdisk", "-n", "2:0:0", "-t", "2:8300", disk)
|
||||
if err := createRoot.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ensure the kernel re-reads the partition table
|
||||
partprobe := exec.Command("partprobe", disk)
|
||||
partprobe.Run()
|
||||
|
||||
// Wait for the system to recognize the changes
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
m.updateProgress(m.currentStep, "Creating new partition table...")
|
||||
|
||||
// Create new GPT partition table
|
||||
sgdiskNew := exec.Command("sgdisk", "--clear", disk)
|
||||
if output, err := sgdiskNew.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to create new partition table: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
// Create EFI System Partition (512MB, FAT32)
|
||||
createEFI := exec.Command("sgdisk", "--new=1:0:+512M", "--typecode=1:EF00", "--change-name=1:EFI System Partition", disk)
|
||||
if output, err := createEFI.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to create EFI partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
// Create root partition (remaining space, Linux filesystem)
|
||||
createRoot := exec.Command("sgdisk", "--new=2:0:0", "--typecode=2:8300", "--change-name=2:Linux Root", disk)
|
||||
if output, err := createRoot.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to create root partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
// Notify the kernel of partition table changes
|
||||
partprobe2 := exec.Command("partprobe", disk)
|
||||
partprobe2.Run()
|
||||
|
||||
// Wait for the system to recognize the new partitions
|
||||
time.Sleep(1 * time.Second)
|
||||
exec.Command("partprobe", disk).Run()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -176,35 +219,55 @@ func (m InstallModel) formatPartitions() error {
|
||||
efiPart := disk + "1"
|
||||
rootPart := disk + "2"
|
||||
|
||||
if strings.Contains(disk, "nvme") || strings.Contains(disk, "mmcblk") {
|
||||
efiPart = disk + "p1"
|
||||
rootPart = disk + "p2"
|
||||
// Wait a bit more to ensure partitions are recognized
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Re-probe the partition table to ensure kernel recognizes the new partitions
|
||||
exec.Command("partprobe", disk).Run()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
// Verify partitions exist
|
||||
if _, err := os.Stat(efiPart); os.IsNotExist(err) {
|
||||
if strings.Contains(disk, "nvme") || strings.Contains(disk, "mmcblk") {
|
||||
efiPart = disk + "p1"
|
||||
rootPart = disk + "p2"
|
||||
}
|
||||
}
|
||||
|
||||
// Double-check that the partitions exist with the correct naming
|
||||
if _, err := os.Stat(efiPart); os.IsNotExist(err) {
|
||||
// Try to list available partitions to help with debugging
|
||||
lsblk := exec.Command("lsblk", "-f", disk)
|
||||
if output, err := lsblk.CombinedOutput(); err == nil {
|
||||
return fmt.Errorf("EFI partition %s not found after partitioning. Available partitions:\n%s", efiPart, string(output))
|
||||
}
|
||||
return fmt.Errorf("EFI partition %s not found after partitioning", efiPart)
|
||||
}
|
||||
|
||||
mkfsEFI := exec.Command("mkfs.fat", "-F32", efiPart)
|
||||
if err := mkfsEFI.Run(); err != nil {
|
||||
return err
|
||||
if output, err := mkfsEFI.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to format EFI partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
if m.config.EnableLUKS {
|
||||
cryptsetup := exec.Command("cryptsetup", "luksFormat", "--type", "luks2", rootPart)
|
||||
cryptsetup.Stdin = strings.NewReader(m.config.RootPassword + "\n")
|
||||
if err := cryptsetup.Run(); err != nil {
|
||||
return err
|
||||
if output, err := cryptsetup.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to format LUKS partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
cryptOpen := exec.Command("cryptsetup", "open", rootPart, "cryptroot")
|
||||
cryptOpen.Stdin = strings.NewReader(m.config.RootPassword + "\n")
|
||||
if err := cryptOpen.Run(); err != nil {
|
||||
return err
|
||||
if output, err := cryptOpen.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to open LUKS partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
rootPart = "/dev/mapper/cryptroot"
|
||||
}
|
||||
|
||||
mkfsBtrfs := exec.Command("mkfs.btrfs", "-f", rootPart)
|
||||
if err := mkfsBtrfs.Run(); err != nil {
|
||||
return err
|
||||
if output, err := mkfsBtrfs.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to format root partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -215,32 +278,58 @@ func (m InstallModel) mountFilesystems() error {
|
||||
rootPart := disk + "2"
|
||||
efiPart := disk + "1"
|
||||
|
||||
// Wait for partitions to be fully recognized
|
||||
time.Sleep(1 * time.Second)
|
||||
exec.Command("partprobe", disk).Run()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
// Handle NVMe and mmcblk device naming
|
||||
if strings.Contains(disk, "nvme") || strings.Contains(disk, "mmcblk") {
|
||||
efiPart = disk + "p1"
|
||||
rootPart = disk + "p2"
|
||||
}
|
||||
|
||||
// Verify partitions exist before mounting
|
||||
if _, err := os.Stat(efiPart); os.IsNotExist(err) {
|
||||
return fmt.Errorf("EFI partition %s not found", efiPart)
|
||||
}
|
||||
if _, err := os.Stat(rootPart); os.IsNotExist(err) {
|
||||
return fmt.Errorf("root partition %s not found", rootPart)
|
||||
}
|
||||
|
||||
if m.config.EnableLUKS {
|
||||
// Check if cryptroot is already open
|
||||
if _, err := os.Stat("/dev/mapper/cryptroot"); os.IsNotExist(err) {
|
||||
cryptOpen := exec.Command("cryptsetup", "open", rootPart, "cryptroot")
|
||||
cryptOpen.Stdin = strings.NewReader(m.config.RootPassword + "\n")
|
||||
if output, err := cryptOpen.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to open LUKS partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
}
|
||||
rootPart = "/dev/mapper/cryptroot"
|
||||
}
|
||||
|
||||
os.MkdirAll("/mnt", 0755)
|
||||
mount := exec.Command("mount", rootPart, "/mnt")
|
||||
if err := mount.Run(); err != nil {
|
||||
return err
|
||||
if output, err := mount.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to mount root partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
// Create btrfs subvolumes
|
||||
btrfsOpts := "subvol=@,compress=zstd,noatime"
|
||||
for _, subvol := range []string{"@", "@home", "@var", "@snapshots"} {
|
||||
create := exec.Command("btrfs", "subvolume", "create", "/mnt/"+subvol)
|
||||
create.Run()
|
||||
if output, err := create.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to create subvolume %s: %w\nOutput: %s", subvol, err, string(output))
|
||||
}
|
||||
}
|
||||
|
||||
exec.Command("umount", "/mnt").Run()
|
||||
|
||||
// Mount root with subvolume
|
||||
mount = exec.Command("mount", "-o", btrfsOpts, rootPart, "/mnt")
|
||||
if err := mount.Run(); err != nil {
|
||||
return err
|
||||
if output, err := mount.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to mount root with subvolumes: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
os.MkdirAll("/mnt/home", 0755)
|
||||
@@ -249,17 +338,23 @@ func (m InstallModel) mountFilesystems() error {
|
||||
os.MkdirAll("/mnt/boot", 0755)
|
||||
|
||||
mountHome := exec.Command("mount", "-o", "subvol=@home,compress=zstd,noatime", rootPart, "/mnt/home")
|
||||
mountHome.Run()
|
||||
if output, err := mountHome.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to mount home subvolume: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
mountVar := exec.Command("mount", "-o", "subvol=@var,compress=zstd,noatime", rootPart, "/mnt/var")
|
||||
mountVar.Run()
|
||||
if output, err := mountVar.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to mount var subvolume: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
mountSnap := exec.Command("mount", "-o", "subvol=@snapshots,compress=zstd,noatime", rootPart, "/mnt/.snapshots")
|
||||
mountSnap.Run()
|
||||
if output, err := mountSnap.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to mount snapshots subvolume: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
mountEFI := exec.Command("mount", efiPart, "/mnt/boot")
|
||||
if err := mountEFI.Run(); err != nil {
|
||||
return err
|
||||
if output, err := mountEFI.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to mount EFI partition: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -511,20 +606,34 @@ editor no
|
||||
|
||||
disk := m.config.Disk
|
||||
rootPart := disk + "2"
|
||||
|
||||
// Handle NVMe and mmcblk device naming
|
||||
if strings.Contains(disk, "nvme") || strings.Contains(disk, "mmcblk") {
|
||||
rootPart = disk + "p2"
|
||||
}
|
||||
|
||||
// For LUKS, we need to reference the encrypted device, not the decrypted one
|
||||
// The bootloader needs to unlock the device first
|
||||
var options string
|
||||
if m.config.EnableLUKS {
|
||||
cryptUUID := ""
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", rootPart)
|
||||
output, _ := blkid.Output()
|
||||
cryptUUID = strings.TrimSpace(string(output))
|
||||
// Get UUID of the encrypted partition (not the mapped device)
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", disk+"2")
|
||||
if strings.Contains(disk, "nvme") || strings.Contains(disk, "mmcblk") {
|
||||
blkid = exec.Command("blkid", "-s", "UUID", "-o", "value", disk+"p2")
|
||||
}
|
||||
output, err := blkid.Output()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get encrypted partition UUID: %w", err)
|
||||
}
|
||||
cryptUUID := strings.TrimSpace(string(output))
|
||||
options = fmt.Sprintf("cryptdevice=UUID=%s:cryptroot root=/dev/mapper/cryptroot rootflags=subvol=@ rw quiet splash", cryptUUID)
|
||||
} else {
|
||||
// Get UUID of the root partition
|
||||
blkid := exec.Command("blkid", "-s", "UUID", "-o", "value", rootPart)
|
||||
output, _ := blkid.Output()
|
||||
output, err := blkid.Output()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get root partition UUID: %w", err)
|
||||
}
|
||||
rootUUID := strings.TrimSpace(string(output))
|
||||
options = fmt.Sprintf("root=UUID=%s rootflags=subvol=@ rw quiet splash", rootUUID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user