H2T (Host-to-target) installs and prevent host pollution (#3978)
* Add host-to-target (H2T) installation mode detection - Add running_from_host() function to detect if running from installed system vs ISO - Function checks for /run/archiso existence (ISO mode) vs host mode - Add clear logging of installation mode on startup - Skip keyboard layout changes when running from host system - Fix Pyright type error in jsonify() by using Any instead of object - Update README to mention installation from existing system This enables archinstall to be run from an existing Arch installation to perform host-to-target installs on other disks/partitions. * match existing style * rem debug * info -> debug
This commit is contained in:
parent
810a50e46c
commit
6b23eff422
|
|
@ -6,7 +6,7 @@
|
|||
[](https://github.com/archlinux/archinstall/actions/workflows/flake8.yaml)
|
||||
|
||||
Just another guided/automated [Arch Linux](https://wiki.archlinux.org/index.php/Arch_Linux) installer with a twist.
|
||||
The installer also doubles as a python library to install Arch Linux and manage services, packages, and other things inside the installed system *(Usually from a live medium)*.
|
||||
The installer also doubles as a python library to install Arch Linux and manage services, packages, and other things inside the installed system *(Usually from a live medium or from an existing installation)*.
|
||||
|
||||
* archinstall [discord](https://discord.gg/aDeMffrxNg) server
|
||||
* archinstall [#archinstall:matrix.org](https://matrix.to/#/#archinstall:matrix.org) Matrix channel
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from archinstall.lib.networking import ping
|
|||
from archinstall.lib.packages.packages import check_package_upgrade
|
||||
from archinstall.tui.ui.components import tui as ttui
|
||||
|
||||
from .lib.general import running_from_host
|
||||
from .lib.hardware import SysInfo
|
||||
from .lib.output import FormattedOutput, debug, error, info, log, warn
|
||||
from .lib.pacman import Pacman
|
||||
|
|
@ -110,6 +111,12 @@ def main() -> int:
|
|||
info(new_version)
|
||||
time.sleep(3)
|
||||
|
||||
if running_from_host():
|
||||
# log which mode we are using
|
||||
debug('Running from Host (H2T Mode)...')
|
||||
else:
|
||||
debug('Running from ISO (Live Mode)...')
|
||||
|
||||
script = arch_config_handler.get_script()
|
||||
|
||||
mod_name = f'archinstall.scripts.{script}'
|
||||
|
|
|
|||
|
|
@ -27,6 +27,17 @@ _VT100_ESCAPE_REGEX = r'\x1B\[[?0-9;]*[a-zA-Z]'
|
|||
_VT100_ESCAPE_REGEX_BYTES = _VT100_ESCAPE_REGEX.encode()
|
||||
|
||||
|
||||
def running_from_host() -> bool:
|
||||
"""
|
||||
Check if running from an installed system.
|
||||
|
||||
Returns True if running from installed system (host mode) for host-to-target install.
|
||||
Returns False if /run/archiso exists (ISO mode).
|
||||
"""
|
||||
is_host = not Path('/run/archiso').exists()
|
||||
return is_host
|
||||
|
||||
|
||||
def generate_password(length: int = 64) -> str:
|
||||
haystack = string.printable # digits, ascii_letters, punctuation (!"#$[] etc) and whitespace
|
||||
return ''.join(secrets.choice(haystack) for _ in range(length))
|
||||
|
|
@ -46,7 +57,7 @@ def clear_vt100_escape_codes_from_str(data: str) -> str:
|
|||
return re.sub(_VT100_ESCAPE_REGEX, '', data)
|
||||
|
||||
|
||||
def jsonify(obj: object, safe: bool = True) -> object:
|
||||
def jsonify(obj: Any, safe: bool = True) -> Any:
|
||||
"""
|
||||
Converts objects into json.dumps() compatible nested dictionaries.
|
||||
Setting safe to True skips dictionary keys starting with a bang (!)
|
||||
|
|
@ -84,7 +95,7 @@ class JSON(json.JSONEncoder, json.JSONDecoder):
|
|||
"""
|
||||
|
||||
@override
|
||||
def encode(self, o: object) -> str:
|
||||
def encode(self, o: Any) -> str:
|
||||
return super().encode(jsonify(o))
|
||||
|
||||
|
||||
|
|
@ -94,7 +105,7 @@ class UNSAFE_JSON(json.JSONEncoder, json.JSONDecoder):
|
|||
"""
|
||||
|
||||
@override
|
||||
def encode(self, o: object) -> str:
|
||||
def encode(self, o: Any) -> str:
|
||||
return super().encode(jsonify(o, safe=False))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from ..exceptions import ServiceException, SysCallError
|
||||
from ..general import SysCommand
|
||||
from ..general import SysCommand, running_from_host
|
||||
from ..output import error
|
||||
|
||||
|
||||
|
|
@ -79,6 +79,11 @@ def get_kb_layout() -> str:
|
|||
|
||||
|
||||
def set_kb_layout(locale: str) -> bool:
|
||||
if running_from_host():
|
||||
# Skip when running from host - no need to change host keymap
|
||||
# The target installation keymap is set via installer.set_keyboard_language()
|
||||
return True
|
||||
|
||||
if len(locale.strip()):
|
||||
if not verify_keyboard_layout(locale):
|
||||
error(f'Invalid keyboard locale specified: {locale}')
|
||||
|
|
|
|||
Loading…
Reference in New Issue