From 83ece36ec3db675a7b7ce711775912186226ca85 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Thu, 7 Nov 2024 23:08:42 +1100 Subject: [PATCH 1/9] Ignore disk encryption config when no password found (#2779) --- archinstall/__init__.py | 3 +-- archinstall/lib/disk/device_model.py | 13 ++++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/archinstall/__init__.py b/archinstall/__init__.py index 5757405e50..aec47685cf 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -255,11 +255,10 @@ def load_config() -> None: arguments['audio_config'] = models.AudioConfiguration.parse_arg(arguments['audio_config']) if arguments.get('disk_encryption', None) is not None and disk_config is not None: - password = arguments.get('encryption_password', '') arguments['disk_encryption'] = disk.DiskEncryption.parse_arg( arguments['disk_config'], arguments['disk_encryption'], - password + arguments.get('encryption_password', '') ) diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py index 78847ce711..75321d5b15 100644 --- a/archinstall/lib/disk/device_model.py +++ b/archinstall/lib/disk/device_model.py @@ -1232,32 +1232,35 @@ def validate_enc(cls, disk_config: DiskLayoutConfiguration) -> bool: def parse_arg( cls, disk_config: DiskLayoutConfiguration, - arg: Dict[str, Any], + disk_encryption: Dict[str, Any], password: str = '' ) -> Optional['DiskEncryption']: if not cls.validate_enc(disk_config): return None + if len(password) < 1: + return None + enc_partitions = [] for mod in disk_config.device_modifications: for part in mod.partitions: - if part.obj_id in arg.get('partitions', []): + if part.obj_id in disk_encryption.get('partitions', []): enc_partitions.append(part) volumes = [] if disk_config.lvm_config: for vol in disk_config.lvm_config.get_all_volumes(): - if vol.obj_id in arg.get('lvm_volumes', []): + if vol.obj_id in disk_encryption.get('lvm_volumes', []): volumes.append(vol) enc = DiskEncryption( - EncryptionType(arg['encryption_type']), + EncryptionType(disk_encryption['encryption_type']), password, enc_partitions, volumes ) - if hsm := arg.get('hsm_device', None): + if hsm := disk_encryption.get('hsm_device', None): enc.hsm_device = Fido2Device.parse_arg(hsm) return enc From 0f4e76f142d90ca1287a11ccd75830bafd2f140d Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Thu, 7 Nov 2024 23:33:34 +1100 Subject: [PATCH 2/9] Update pre-commit hooks (#2777) * Add missing pydantic dependencies to pre-commit mypy hook * Add pylint to pre-commit checks --- .pre-commit-config.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b97a7a170f..3c0acdd70b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,7 +39,19 @@ repos: hooks: - id: mypy fail_fast: true + additional_dependencies: + - pydantic + - pydantic-settings - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.7.2 hooks: - id: ruff + - repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] + fail_fast: true + require_serial: true From 7098a6a8486f5d4d9371ed64576fbafce9e944e0 Mon Sep 17 00:00:00 2001 From: Vincent Date: Thu, 7 Nov 2024 16:17:32 +0100 Subject: [PATCH 3/9] Document network config in config-sample.json (#2781) Specifically document the CIDR notation of the IP address --- examples/config-sample.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/config-sample.json b/examples/config-sample.json index c9beb4805d..57c1e1dab1 100644 --- a/examples/config-sample.json +++ b/examples/config-sample.json @@ -99,11 +99,14 @@ "type": "manual", "nics": [ { - "iface": null, - "ip": null, + "iface": "eno1", + "ip": "192.168.1.15/24", "dhcp": true, - "gateway": null, - "dns": null + "gateway": "192.168.1.1", + "dns": [ + "192.168.1.1", + "9.9.9.9" + ] } ] }, From 26cf04655ae1e0ce38cb557a43e5b82f385d1302 Mon Sep 17 00:00:00 2001 From: Vincent Date: Thu, 7 Nov 2024 21:35:50 +0100 Subject: [PATCH 4/9] Document LUKS encryption password in creds-sample.json (#2782) --- examples/creds-sample.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/creds-sample.json b/examples/creds-sample.json index 530a2465ee..70645fd8ac 100644 --- a/examples/creds-sample.json +++ b/examples/creds-sample.json @@ -4,5 +4,6 @@ "sudo": true, "username": "archinstall" } - ] + ], + "encryption_password": "..." } From c8333ee2a67dfb2510c0ebcd6ee053760d1e8633 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 07:36:39 +1100 Subject: [PATCH 5/9] chore(deps): update pre-commit hook astral-sh/ruff-pre-commit to v0.7.3 (#2784) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3c0acdd70b..c481d36cea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: - pydantic - pydantic-settings - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.2 + rev: v0.7.3 hooks: - id: ruff - repo: local From fbc9431697b3e7eac02694b36192ee2d536791b3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 07:48:01 +1100 Subject: [PATCH 6/9] fix(deps): update dependency ruff to v0.7.3 (#2785) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f304fcd93c..288c3909ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ dev = [ "mypy==1.13.0", "flake8==7.1.1", "pre-commit==4.0.1", - "ruff==0.7.2", + "ruff==0.7.3", "pylint==3.3.1", "pylint-pydantic==0.3.2", ] From 9951c90bf9ce52bb01cd46b19a15527d9a4c8a83 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Sat, 9 Nov 2024 19:49:23 +1100 Subject: [PATCH 7/9] Fix local mirror selection (#2789) --- archinstall/lib/mirrors.py | 130 +++++++++++++++++++++--------- archinstall/lib/models/mirrors.py | 10 ++- 2 files changed, 97 insertions(+), 43 deletions(-) diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py index 7eab1946c8..ca92f3f3ee 100644 --- a/archinstall/lib/mirrors.py +++ b/archinstall/lib/mirrors.py @@ -1,6 +1,6 @@ import time import json -import pathlib +from pathlib import Path from dataclasses import dataclass, field from enum import Enum from typing import Dict, Any, List, Optional, TYPE_CHECKING @@ -257,29 +257,51 @@ def select_mirror_regions(preset_values: Dict[str, List[str]] = {}) -> Dict[str, else: preselected = list(preset_values.keys()) - mirrors = list_mirrors() + remote_mirrors = list_mirrors_from_remote() + mirrors: Dict[str, list[str]] = {} - choice = Menu( - _('Select one of the regions to download packages from'), - list(mirrors.keys()), - preset_values=preselected, - multi=True, - allow_reset=True - ).run() + if remote_mirrors: + choice = Menu( + _('Select one of the regions to download packages from'), + list(remote_mirrors.keys()), + preset_values=preselected, + multi=True, + allow_reset=True + ).run() - match choice.type_: - case MenuSelectionType.Reset: - return {} - case MenuSelectionType.Skip: - return preset_values - case MenuSelectionType.Selection: - return { - selected: [ - f"{mirror.url}$repo/os/$arch" for mirror in sort_mirrors_by_performance(mirrors[selected]) - ] for selected in choice.multi_value - } + match choice.type_: + case MenuSelectionType.Reset: + return {} + case MenuSelectionType.Skip: + return preset_values + case MenuSelectionType.Selection: + for region in choice.multi_value: + mirrors.setdefault(region, []) + for mirror in _sort_mirrors_by_performance(remote_mirrors[region]): + mirrors[region].append(mirror.server_url) + return mirrors + else: + local_mirrors = list_mirrors_from_local() + + choice = Menu( + _('Select one of the regions to download packages from'), + list(local_mirrors.keys()), + preset_values=preselected, + multi=True, + allow_reset=True + ).run() - return {} + match choice.type_: + case MenuSelectionType.Reset: + return {} + case MenuSelectionType.Skip: + return preset_values + case MenuSelectionType.Selection: + for region in choice.multi_value: + mirrors[region] = local_mirrors[region] + return mirrors + + return mirrors def select_custom_mirror(prompt: str = '', preset: List[CustomMirror] = []) -> list[CustomMirror]: @@ -287,11 +309,35 @@ def select_custom_mirror(prompt: str = '', preset: List[CustomMirror] = []) -> l return custom_mirrors -def sort_mirrors_by_performance(mirror_list: List[MirrorStatusEntryV3]) -> List[MirrorStatusEntryV3]: +def list_mirrors_from_remote() -> Optional[Dict[str, List[MirrorStatusEntryV3]]]: + if not storage['arguments']['offline']: + url = "https://archlinux.org/mirrors/status/json/" + attempts = 3 + + for attempt_nr in range(attempts): + try: + mirrorlist = fetch_data_from_url(url) + return _parse_remote_mirror_list(mirrorlist) + except Exception as e: + debug(f'Error while fetching mirror list: {e}') + time.sleep(attempt_nr + 1) + + debug('Unable to fetch mirror list remotely, falling back to local mirror list') + + return None + + +def list_mirrors_from_local() -> Dict[str, list[str]]: + with Path('/etc/pacman.d/mirrorlist').open('r') as fp: + mirrorlist = fp.read() + return _parse_locale_mirrors(mirrorlist) + + +def _sort_mirrors_by_performance(mirror_list: List[MirrorStatusEntryV3]) -> List[MirrorStatusEntryV3]: return sorted(mirror_list, key=lambda mirror: (mirror.score, mirror.speed)) -def _parse_mirror_list(mirrorlist: str) -> Dict[str, List[MirrorStatusEntryV3]]: +def _parse_remote_mirror_list(mirrorlist: str) -> Dict[str, List[MirrorStatusEntryV3]]: mirror_status = MirrorStatusListV3(**json.loads(mirrorlist)) sorting_placeholder: Dict[str, List[MirrorStatusEntryV3]] = {} @@ -324,23 +370,27 @@ def _parse_mirror_list(mirrorlist: str) -> Dict[str, List[MirrorStatusEntryV3]]: return sorted_by_regions -def list_mirrors() -> Dict[str, List[MirrorStatusEntryV3]]: - if not storage['arguments']['offline']: - url = "https://archlinux.org/mirrors/status/json/" - attempts = 3 +def _parse_locale_mirrors(mirrorlist: str) -> Dict[str, List[str]]: + lines = mirrorlist.splitlines() - for attempt_nr in range(attempts): - try: - mirrorlist = fetch_data_from_url(url) - return _parse_mirror_list(mirrorlist) - except Exception as e: - debug(f'Error while fetching mirror list: {e}') - time.sleep(attempt_nr + 1) + # remove empty lines + lines = [line for line in lines if line] - debug('Unable to fetch mirror list remotely, falling back to local mirror list') + mirror_list: Dict[str, List[str]] = {} - # we'll use the local mirror list if the offline flag is set - # or if fetching the mirror list remotely failed - with pathlib.Path('/etc/pacman.d/mirrorlist').open('r') as fp: - mirrorlist = fp.read() - return _parse_mirror_list(mirrorlist) + current_region = '' + for idx, line in enumerate(lines): + line = line.strip() + + if line.lower().startswith('server'): + if not current_region: + for i in range(idx - 1, 0, -1): + if lines[i].startswith('##'): + current_region = lines[i].replace('#', '').strip() + mirror_list.setdefault(current_region, []) + break + + url = line.removeprefix('Server = ') + mirror_list[current_region].append(url) + + return mirror_list diff --git a/archinstall/lib/models/mirrors.py b/archinstall/lib/models/mirrors.py index 304d5371b9..dc95644da4 100644 --- a/archinstall/lib/models/mirrors.py +++ b/archinstall/lib/models/mirrors.py @@ -10,7 +10,7 @@ ) from ..networking import ping, DownloadTimer -from ..output import info, debug +from ..output import debug class MirrorStatusEntryV3(pydantic.BaseModel): @@ -35,6 +35,10 @@ class MirrorStatusEntryV3(pydantic.BaseModel): _port: int | None = None _speedtest_retries: int | None = None + @property + def server_url(self) -> str: + return f'{self.url}$repo/os/$arch' + @property def speed(self) -> float: if self._speed is None: @@ -45,7 +49,7 @@ def speed(self) -> float: _retry = 0 while _retry < self._speedtest_retries and self._speed is None: - info(f"Checking download speed of {self._hostname}[{self.score}] by fetching: {self.url}core/os/x86_64/core.db") + debug(f"Checking download speed of {self._hostname}[{self.score}] by fetching: {self.url}core/os/x86_64/core.db") req = urllib.request.Request(url=f"{self.url}core/os/x86_64/core.db") try: @@ -81,7 +85,7 @@ def latency(self) -> float | None: We do this because some hosts blocks ICMP so we'll have to rely on .speed() instead which is slower. """ if self._latency is None: - info(f"Checking latency for {self.url}") + debug(f"Checking latency for {self.url}") self._latency = ping(self._hostname, timeout=2) debug(f" latency: {self._latency}") From 4a9aca2f78871ce218bd7e8e6389753e74e44e98 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 9 Nov 2024 10:01:25 +0100 Subject: [PATCH 8/9] Added missing package dependencies related to fs-operations (#2792) --- PKGBUILD | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PKGBUILD b/PKGBUILD index 7a8affeab3..b3974ca690 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -27,6 +27,11 @@ depends=( 'python-simple-term-menu' 'systemd' 'util-linux' + 'xfsprogs' + 'lvm2' + 'f2fs-tools' + 'ntfs-3g' + 'reiserfsprogs' ) makedepends=( 'python-setuptools' From de664dfa399d77785410ec9c0d13868af3da9831 Mon Sep 17 00:00:00 2001 From: Jack Desert Date: Sat, 9 Nov 2024 04:16:15 -0500 Subject: [PATCH 9/9] Include xss-set when installing i3wm (#2791) Co-authored-by: jack --- archinstall/default_profiles/desktops/i3.py | 1 + 1 file changed, 1 insertion(+) diff --git a/archinstall/default_profiles/desktops/i3.py b/archinstall/default_profiles/desktops/i3.py index 8c7f38a783..7f16ce05f8 100644 --- a/archinstall/default_profiles/desktops/i3.py +++ b/archinstall/default_profiles/desktops/i3.py @@ -18,6 +18,7 @@ def packages(self) -> list[str]: 'i3lock', 'i3status', 'i3blocks', + 'xss-set', 'xterm', 'lightdm-gtk-greeter', 'lightdm',