diff --git a/INSTALL.md b/INSTALL.md index b5baec2..bde13c2 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -29,8 +29,11 @@ Boot desde el USB. Entras como `root` automáticamente. lsblk ``` -Confirma que el NVMe es `nvme0n1` y el SSD SATA de 1TB es `sda`. Si no, edita los -JSON antes de seguir. +Los discos se autodetectan por NO removible (`RM=0`): el USB instalador (`sdb`) +queda fuera y da igual si el disco de sistema es `nvme0n1` o un SSD PCIe que sale +como `sda`. Confirma con `lsblk` que solo tus discos reales tienen `RM` a `0`. El +1º (nvme si existe) es el de sistema, el 2º (si hay) va a `/home`. Para forzarlo: +`gen-disk-config.py BASE.json /dev/SISTEMA [/dev/HOME]`. ## 4. Clonar y lanzar diff --git a/README.md b/README.md index 73979ba..135633e 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,19 @@ privado), nombre y email de git. Después, sin más intervención: ## ⚠️ Antes de lanzar -- **Se borran DOS discos** (`"wipe": true` en ambos). Recrea el esquema actual: - - `/dev/nvme0n1` → ESP 512M (`/boot/efi`) + `/boot` ext4 1G + `/` btrfs (resto) - - `/dev/sda` → ext4 todo el disco en `/home` (**ojo: esto destruye el HDD de datos**) +- **Se borran los discos FIJOS detectados** (`"wipe": true`). Los discos se + autodetectan filtrando por NO removible (`RM=0` en `lsblk`), así el USB + instalador (`sdb`, removible) queda fuera y da igual que el SSD sea `nvme0n1` + o un SSD PCIe que enumera como `sda`. Esquema: + - **Disco de sistema** (1º; nvme si existe) → ESP 512M (`/boot/efi`) + `/boot` + ext4 1G + `/` btrfs (resto) + - **2º disco fijo** (si hay) → ext4 todo el disco en `/home` (**ojo: destruye + el disco de datos**). Si solo hay 1 disco, `/home` vive dentro del `/` btrfs. - swap = zram (`"swap": true`), sin partición de swap - bootloader **GRUB** (coherente con ESP en `/boot/efi` + `/boot` separado) - Verifica los nombres con `lsblk`; si tus discos no son `nvme0n1`/`sda`, edítalos. + Verifica con `lsblk` qué discos quedan como fijos. Para forzar nombres a mano: + `gen-disk-config.py BASE.json /dev/SISTEMA [/dev/HOME]`. - **Esquema de particiones de archinstall** cambia entre versiones, y el particionado manual multi-disco es lo más sensible. Si archinstall se queja del `disk_config`, abre `archinstall` interactivo, define los discos a mano, usa diff --git a/shared/gen-disk-config.py b/shared/gen-disk-config.py index 27f86f0..6ada3a7 100644 --- a/shared/gen-disk-config.py +++ b/shared/gen-disk-config.py @@ -5,19 +5,30 @@ # (250G/1TB): por eso se calcula en tiempo de instalación con los propios modelos # de archinstall (válido ante cambios de schema entre versiones). # -# gen-disk-config.py BASE.json [NVME_DEV] [SDA_DEV] > merged.json +# gen-disk-config.py BASE.json [SYS_DEV] [HOME_DEV] > merged.json # -# Layout (replica el hardware): NVMe = ESP 512M + /boot 1G ext4 + / btrfs (resto); -# SDA = /home ext4 (todo). swap = zram (lo pone "swap": true del base). -# Si SDA no existe (portatil de 1 disco), se omite: /home queda dentro del / btrfs. -import json, sys +# Los discos se autodetectan: no se puede contar discos para decidir el layout +# porque el USB instalador tambien aparece como disco (p.ej. sdb). Filtramos por +# NO removible (RM=0): el USB es removible y queda fuera; el ISO de la VM es 'rom' +# y tampoco cuenta. Asi da igual que el disco de sistema sea nvme0n1 o un SSD +# PCIe que enumera como sda. Pasa SYS_DEV/HOME_DEV para forzar nombres a mano. +# +# Layout (replica el hardware): disco de sistema = ESP 512M + /boot 1G ext4 + +# / btrfs (resto); segundo disco = /home ext4 (todo). swap = zram ("swap": true +# del base). Si solo hay 1 disco (portatil), /home queda dentro del / btrfs. +import json, subprocess, sys from pathlib import Path -from archinstall.lib.disk.device_handler import device_handler -from archinstall.lib.models.device import ( - DiskLayoutConfiguration, DiskLayoutType, DeviceModification, - PartitionModification, ModificationStatus, PartitionType, - FilesystemType, PartitionFlag, Size, Unit, -) +# archinstall solo existe en el entorno live; el --selftest corre en cualquier +# sitio porque pick_fixed no lo necesita. ponytail: se importa al usar main(). +try: + from archinstall.lib.disk.device_handler import device_handler + from archinstall.lib.models.device import ( + DiskLayoutConfiguration, DiskLayoutType, DeviceModification, + PartitionModification, ModificationStatus, PartitionType, + FilesystemType, PartitionFlag, Size, Unit, + ) +except ImportError: + device_handler = None MiB = 1024 ** 2 END_MARGIN = MiB # deja 1 MiB al final para la cabecera GPT de respaldo @@ -56,21 +67,40 @@ def sda_mods(dev): total - start - END_MARGIN, ss, FilesystemType.EXT4, "/home"), ]) +def pick_fixed(lsblk_out): + # Discos NO removibles, en orden de kernel. Excluye el USB instalador (RM=1) + # y el ISO de la VM (TYPE=rom). nvme va antes que sda si ambos existen. + disks = [] + for line in lsblk_out.splitlines(): + name, rm, typ = line.split() + if typ == "disk" and rm == "0": + disks.append(f"/dev/{name}") + return sorted(disks, key=lambda d: (0 if "nvme" in d else 1, d)) + +def fixed_disks(): + return pick_fixed(subprocess.check_output( + ["lsblk", "-dnro", "NAME,RM,TYPE"], text=True)) + def main(): + if device_handler is None: + sys.exit("archinstall no disponible (¿estás en el entorno live?)") base_path = sys.argv[1] - nvme = sys.argv[2] if len(sys.argv) > 2 else "/dev/nvme0n1" - sda = sys.argv[3] if len(sys.argv) > 3 else "/dev/sda" + override = sys.argv[2:] # SYS_DEV [HOME_DEV] para forzar a mano + disks = override if override else fixed_disks() + if not disks: + sys.exit("No encuentro ningun disco fijo no removible (revisa lsblk)") - dev_nvme = device_handler.get_device(Path(nvme)) - if not dev_nvme: - sys.exit(f"No encuentro el disco de sistema {nvme} (revisa lsblk)") + dev_sys = device_handler.get_device(Path(disks[0])) + if not dev_sys: + sys.exit(f"No encuentro el disco de sistema {disks[0]} (revisa lsblk)") - # 2 discos -> layout hardware: NVMe=sistema, SDA=/home aparte. - # 1 disco (portatil) -> todo en el NVMe; /home vive dentro del btrfs raiz. - dev_sda = device_handler.get_device(Path(sda)) - mods = [nvme_mods(dev_nvme)] - if dev_sda: - mods.append(sda_mods(dev_sda)) + # >=2 discos fijos -> sistema + /home aparte. 1 disco (portatil) -> todo + # en el de sistema; /home vive dentro del btrfs raiz. + mods = [nvme_mods(dev_sys)] + if len(disks) > 1: + dev_home = device_handler.get_device(Path(disks[1])) + if dev_home: + mods.append(sda_mods(dev_home)) layout = DiskLayoutConfiguration( config_type=DiskLayoutType.Manual, @@ -80,5 +110,19 @@ def main(): cfg["disk_config"] = layout.json() json.dump(cfg, sys.stdout, indent=2) +def _selftest(): + # portatil: SSD PCIe = sda (fijo), USB instalador = sdb (RM=1), ISO = sr0 + laptop = "sda 0 disk\nsdb 1 disk\nsr0 1 rom" + assert pick_fixed(laptop) == ["/dev/sda"], pick_fixed(laptop) + # hardware/VM: nvme = sistema, sda = /home; nvme primero aunque ordene despues + two = "sda 0 disk\nnvme0n1 0 disk" + assert pick_fixed(two) == ["/dev/nvme0n1", "/dev/sda"], pick_fixed(two) + # solo USB conectado -> sin discos fijos (main aborta) + assert pick_fixed("sdb 1 disk\nsr0 1 rom") == [] + print("ok") + if __name__ == "__main__": - main() + if sys.argv[1:2] == ["--selftest"]: + _selftest() + else: + main()