Repository: archlinux/archinstall

Issue:
diskconf "leave as is" option is broken
Error when using config without diskconfig line:

```
sudo archinstall --config /tmp/user_configuration.json --creds templates/root.json --silent
Testing connectivity to the Arch Linux mirrors...
Traceback (most recent call last):
  File "/home/manjaro/archinstall/venvv/bin/archinstall", line 8, in <module>
    sys.exit(run_as_a_module())
             ^^^^^^^^^^^^^^^^^
  File "/home/manjaro/archinstall/venvv/lib/python3.11/site-packages/archinstall/__init__.py", line 291, in run_as_a_module
    importlib.import_module(mod_name)
  File "/usr/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/manjaro/archinstall/venvv/lib/python3.11/site-packages/archinstall/scripts/guided.py", line 250, in <module>
    archinstall.arguments['disk_config'],
    ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
KeyError: 'disk_config'
```


When using diskcinfig: null (ran from ansible)

```
"Traceback (most recent call last):\n  File \"/tmp/venv_archinstall/bin/archinstall\", line 8, in <module>\n    sys.exit(run_as_a_module())\n             ^^^^^^^^^^^^^^^^^\n  File \"/tmp/venv_archinstall/lib/python3.11/site-packages/archinstall/__init__.py\", line 291, in run_as_a_module\n    importlib.import_module(mod_name)\n  File \"/usr/lib/python3.11/importlib/__init__.py\", line 126, in import_module\n    return _bootstrap._gcd_import(name[level:], package, level)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"<frozen importlib._bootstrap>\", line 1204, in _gcd_import\n  File \"<frozen importlib._bootstrap>\", line 1176, in _find_and_load\n  File \"<frozen importlib._bootstrap>\", line 1147, in _find_and_load_unlocked\n  File \"<frozen importlib._bootstrap>\", line 690, in _load_unlocked\n  File \"<frozen importlib._bootstrap_external>\", line 940, in exec_module\n  File \"<frozen importlib._bootstrap>\", line 241, in _call_with_frames_removed\n  File \"/tmp/venv_archinstall/lib/python3.11/site-packages/archinstall/scripts/guided.py\", line 254, in <module>\n    fs_handler.perform_filesystem_operations()\n  File \"/tmp/venv_archinstall/lib/python3.11/site-packages/archinstall/lib/disk/filesystem.py\", line 28, in perform_filesystem_operations\n    if self._disk_config.config_type == DiskLayoutType.Pre_mount:\n       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nAttributeError: 'NoneType' object has no attribute 'config_type'",
    "stderr_lines": [
        "Traceback (most recent call last):",
        "  File \"/tmp/venv_archinstall/bin/archinstall\", line 8, in <module>",
        "    sys.exit(run_as_a_module())",
        "             ^^^^^^^^^^^^^^^^^",
        "  File \"/tmp/venv_archinstall/lib/python3.11/site-packages/archinstall/__init__.py\", line 291, in run_as_a_module",
        "    importlib.import_module(mod_name)",
        "  File \"/usr/lib/python3.11/importlib/__init__.py\", line 126, in import_module",
        "    return _bootstrap._gcd_import(name[level:], package, level)",
        "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^",
        "  File \"<frozen importlib._bootstrap>\", line 1204, in _gcd_import",
        "  File \"<frozen importlib._bootstrap>\", line 1176, in _find_and_load",
        "  File \"<frozen importlib._bootstrap>\", line 1147, in _find_and_load_unlocked",
        "  File \"<frozen importlib._bootstrap>\", line 690, in _load_unlocked",
        "  File \"<frozen importlib._bootstrap_external>\", line 940, in exec_module",
        "  File \"<frozen importlib._bootstrap>\", line 241, in _call_with_frames_removed",
        "  File \"/tmp/venv_archinstall/lib/python3.11/site-packages/archinstall/scripts/guided.py\", line 254, in <module>",
        "    fs_handler.perform_filesystem_operations()",
        "  File \"/tmp/venv_archinstall/lib/python3.11/site-packages/archinstall/lib/disk/filesystem.py\", line 28, in perform_filesystem_operations",
        "    if self._disk_config.config_type == DiskLayoutType.Pre_mount:",
        "       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^",
        "AttributeError: 'NoneType' object has no attribute 'config_type'"
```

Config file used:
```
{
    "additional-repositories": [],
    "archinstall-language": "English",
    "audio_config": {
        "audio": "pulseaudio"
    },
    "bootloader": "Grub",
    "config_version": "2.6.3",
    "debug": false,
    "disk_config": null,
    "hostname": "{{ pc_name }}",
    "kernels": [
        "linux"
    ],
    "locale_config": {
        "kb_layout": "br-abnt2",
        "sys_enc": "UTF-8",
        "sys_lang": "en_US"
    },
    "mirror_config": {
        "custom_mirrors": [],
        "mirror_regions": {
            "Brazil": [
                "https://mirror.ufscar.br/archlinux/$repo/os/$arch",
                "http://mirror.ufscar.br/archlinux/$repo/os/$arch",
                "http://mirror.ufam.edu.br/archlinux/$repo/os/$arch",
                "http://linorg.usp.br/archlinux/$repo/os/$arch",
                "http://archlinux.c3sl.ufpr.br/$repo/os/$arch"
            ]
        }
    },
    "network_config": {},
    "no_pkg_lookups": false,
    "ntp": true,
    "offline": false,
    "packages": [
        "git",
        "ansible"
    ],
    "parallel downloads": 5,
    "profile_config": {
        "gfx_driver": "All open-source",
        "greeter": "sddm",
        "profile": {
            "custom_settings": {
                "Kde": {}
            },
            "details": [
                "Kde"
            ],
            "main": "Desktop"
        }
    },
    "script": "guided",
    "silent": false,
    "swap": false,
    "timezone": "America/Sao_Paulo",
    "version": "2.6.3"
}
```




Discussion:
Great work uncovering this. With the fix I submitted the following would be needed in your configuration file.

```
    "disk_config": {
        "config_type": "pre_mounted_config",
        "mountpoint": "/mnt/archinstall"
    },
```

Resolving patch:
diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py
--- a/archinstall/lib/disk/device_model.py
+++ b/archinstall/lib/disk/device_model.py
@@ -42,12 +42,20 @@ def display_msg(self) -> str:
 class DiskLayoutConfiguration:
 	config_type: DiskLayoutType
 	device_modifications: List[DeviceModification] = field(default_factory=list)
+	# used for pre-mounted config
+	mountpoint: Optional[Path] = None
 
 	def json(self) -> Dict[str, Any]:
-		return {
-			'config_type': self.config_type.value,
-			'device_modifications': [mod.json() for mod in self.device_modifications]
-		}
+		if self.config_type == DiskLayoutType.Pre_mount:
+			return {
+				'config_type': self.config_type.value,
+				'mountpoint': str(self.mountpoint)
+			}
+		else:
+			return {
+				'config_type': self.config_type.value,
+				'device_modifications': [mod.json() for mod in self.device_modifications]
+			}
 
 	@classmethod
 	def parse_arg(cls, disk_config: Dict[str, List[Dict[str, Any]]]) -> Optional[DiskLayoutConfiguration]:
@@ -64,6 +72,21 @@ def parse_arg(cls, disk_config: Dict[str, List[Dict[str, Any]]]) -> Optional[Dis
 			device_modifications=device_modifications
 		)
 
+		if config_type == DiskLayoutType.Pre_mount.value:
+			if not (mountpoint := disk_config.get('mountpoint')):
+				raise ValueError('Must set a mountpoint when layout type is pre-mount')
+
+			path = Path(str(mountpoint))
+
+			mods = device_handler.detect_pre_mounted_mods(path)
+			device_modifications.extend(mods)
+
+			storage['MOUNT_POINT'] = path
+
+			config.mountpoint = path
+
+			return config
+
 		for entry in disk_config.get('device_modifications', []):
 			device_path = Path(entry.get('device', None)) if entry.get('device', None) else None
 
diff --git a/archinstall/lib/interactions/disk_conf.py b/archinstall/lib/interactions/disk_conf.py
--- a/archinstall/lib/interactions/disk_conf.py
+++ b/archinstall/lib/interactions/disk_conf.py
@@ -145,7 +145,8 @@ def select_disk_config(
 
 				return disk.DiskLayoutConfiguration(
 					config_type=disk.DiskLayoutType.Pre_mount,
-					device_modifications=mods
+					device_modifications=mods,
+					mountpoint=path
 				)
 
 			preset_devices = [mod.device for mod in preset.device_modifications] if preset else []


Test patch: