index : archinstall32 | |
Archlinux32 installer | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | .github/workflows/iso-build.yaml | 3 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | archinstall/__init__.py | 27 | ||||
-rw-r--r-- | archinstall/lib/general.py | 4 | ||||
-rw-r--r-- | archinstall/lib/installer.py | 7 | ||||
-rw-r--r-- | archinstall/lib/user_interaction.py | 19 | ||||
-rw-r--r-- | docs/installing/guided.rst | 108 | ||||
-rw-r--r-- | examples/custom-command-sample.json | 1 | ||||
-rw-r--r-- | examples/guided.py | 37 |
diff --git a/.github/workflows/iso-build.yaml b/.github/workflows/iso-build.yaml index 106bac4a..d603cdcb 100644 --- a/.github/workflows/iso-build.yaml +++ b/.github/workflows/iso-build.yaml @@ -15,6 +15,9 @@ on: - '**.md' - 'LICENSE' - 'PKGBUILD' + release: + types: + - created jobs: build: @@ -24,7 +24,7 @@ Or use `pip install --upgrade archinstall` to use as a library. Assuming you are on an Arch Linux live-ISO and booted into EFI mode. - # python -m archinstall --script guided + # archinstall ## Running from a declarative configuration file or URL @@ -34,7 +34,7 @@ Prequisites: Assuming you are on a Arch Linux live-ISO and booted into EFI mode. - # python -m archinstall --config <path to config file or URL> --vars '<space_seperated KEY=VALUE pairs>' + # archinstall --config <path to config file or URL> [optional: --vars '<space_seperated KEY=VALUE pairs>'] # Help? diff --git a/archinstall/__init__.py b/archinstall/__init__.py index ee4748f6..b914c7ec 100644 --- a/archinstall/__init__.py +++ b/archinstall/__init__.py @@ -23,7 +23,7 @@ from .lib.user_interaction import * parser = ArgumentParser() -__version__ = "2.2.0.dev1" +__version__ = "2.2.0.RC1" def initialize_arguments(): @@ -32,16 +32,7 @@ def initialize_arguments(): parser.add_argument("--silent", action="store_true", help="Warning!!! No prompts, ignored if config is not passed") parser.add_argument("--script", default="guided", nargs="?", help="Script to run for installation", type=str) - parser.add_argument("--vars", - metavar="KEY=VALUE", - nargs='?', - help="Set a number of key-value pairs " - "(do not put spaces before or after the = sign). " - "If a value contains spaces, you should define " - "it with double quotes: " - 'foo="this is a sentence". Note that ' - "values are always treated as strings.") - args = parser.parse_args() + args, unknowns = parser.parse_known_args() if args.config is not None: try: # First, let's check if this is a URL scheme instead of a filename @@ -57,13 +48,13 @@ def initialize_arguments(): print(e) # Installation can't be silent if config is not passed config["silent"] = args.silent - if args.vars is not None: - try: - for var in args.vars.split(' '): - key, val = var.split("=") - config[key] = val - except Exception as e: - print(e) + for arg in unknowns: + if '--' == arg[:2]: + if '=' in arg: + key, val = [x.strip() for x in arg[2:].split('=', 1)] + else: + key, val = arg[2:], True + config[key] = val config["script"] = args.script return config diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index 249c7890..3b62c891 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -333,6 +333,10 @@ class SysCommand: while self.session.ended is None: self.session.poll() + if self.peak_output: + sys.stdout.write('\n') + sys.stdout.flush() + except SysCallError: return False diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 29b3bc1a..0044532f 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1,6 +1,6 @@ from .disk import * from .hardware import * -from .locale_helpers import verify_x11_keyboard_layout +from .locale_helpers import verify_keyboard_layout, verify_x11_keyboard_layout from .mirrors import * from .storage import storage from .user_interaction import * @@ -453,6 +453,7 @@ class Installer: self.pacstrap('efibootmgr') o = b''.join(SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')) SysCommand('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') + self.helper_flags['bootloader'] = True return True else: root_device = subprocess.check_output(f'basename "$(readlink -f /sys/class/block/{root_partition.path.replace("/dev/", "")}/..)"', shell=True).decode().strip() @@ -460,7 +461,7 @@ class Installer: root_device = f"{root_partition.path}" o = b''.join(SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc /dev/{root_device}')) SysCommand('/usr/bin/arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg') - self.helper_flags['bootloader'] = bootloader + self.helper_flags['bootloader'] = True return True else: raise RequirementError(f"Unknown (or not yet implemented) bootloader requested: {bootloader}") @@ -546,6 +547,8 @@ class Installer: self.log(f"Invalid x11-keyboard language specified: {language}", fg="red", level=logging.ERROR) return False + from .systemd import Boot + with Boot(self) as session: session.SysCommand(["localectl", "set-x11-keymap", '""']) diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index d3548e6b..a6b34f67 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -17,7 +17,7 @@ from .hardware import AVAILABLE_GFX_DRIVERS, has_uefi from .locale_helpers import list_keyboard_languages, verify_keyboard_layout, search_keyboard_layout from .networking import list_interfaces from .output import log -from .profiles import Profile +from .profiles import Profile, list_profiles # TODO: Some inconsistencies between the selection processes. @@ -843,28 +843,25 @@ def select_disk(dict_o_disks): raise DiskError('select_disk() requires a non-empty dictionary of disks to select from.') -def select_profile(options): +def select_profile(): """ - Asks the user to select a profile from the `options` dictionary parameter. - Usually this is combined with :ref:`archinstall.list_profiles`. - - :param options: A `dict` where keys are the profile name, value should be a dict containing profile information. - :type options: dict + Asks the user to select a profile from the available profiles. :return: The name/dictionary key of the selected profile :rtype: str """ - profiles = sorted(list(options)) + shown_profiles = sorted(list(list_profiles(filter_top_level_profiles=True))) + actual_profiles_raw = shown_profiles + sorted([profile for profile in list_profiles() if profile not in shown_profiles]) - if len(profiles) >= 1: - for index, profile in enumerate(profiles): + if len(shown_profiles) >= 1: + for index, profile in enumerate(shown_profiles): print(f"{index}: {profile}") print(' -- The above list is a set of pre-programmed profiles. --') print(' -- They might make it easier to install things like desktop environments. --') print(' -- (Leave blank and hit enter to skip this step and continue) --') - selected_profile = generic_select(profiles, 'Enter a pre-programmed profile name if you want to install one: ', options_output=False) + selected_profile = generic_select(actual_profiles_raw, 'Enter a pre-programmed profile name if you want to install one: ', options_output=False) if selected_profile: return Profile(None, selected_profile) else: diff --git a/docs/installing/guided.rst b/docs/installing/guided.rst index 88b4e480..e442d927 100644 --- a/docs/installing/guided.rst +++ b/docs/installing/guided.rst @@ -26,17 +26,113 @@ Running the guided installation To install archinstall and subsequently the guided installer, simply do the following: -.. code::bash - # pacman -S python-archinstall +.. code-block:: sh + + pacman -S python-archinstall And to run it, execute archinstall as a Python module: -.. code::bash - # python -m archinstall guided +.. code-block:: sh -| The guided parameter is optional as it's the default behavior. + python -m archinstall --script guided + +| The ``--script guided`` argument is optional as it's the default behavior. | But this will start the process of guiding you through a installation of a quite minimal Arch Linux experience. +Installing directly from a config file +-------------------------------------- + +.. note:: + Edit the following json according to your needs, + save this as a json file, and provide the local or remote path (URL) + +.. code-block:: json + + { + "audio": "pipewire", + "bootloader": "systemd-bootctl", + "custom-commands": [ + "cd /home/devel; git clone https://aur.archlinux.org/paru.git", + "chown -R devel:devel /home/devel/paru", + "usermod -aG docker devel" + ], + "!encryption-password": "supersecret", + "filesystem": "btrfs", + "harddrive": { + "path": "/dev/nvme0n1" + }, + "hostname": "development-box", + "kernels": [ + "linux" + ], + "keyboard-language": "us", + "mirror-region": { + "Worldwide": { + "https://mirror.rackspace.com/archlinux/$repo/os/$arch": true + } + }, + "nic": { + "NetworkManager": true + }, + "packages": ["docker", "git", "wget", "zsh"], + "profile": "gnome", + "services": ["docker"], + "superusers": { + "devel": { + "!password": "devel" + } + }, + "timezone": "US/Eastern", + "users": {} + } + +To run it, execute archinstall as a Python module: + +.. code-block:: sh + + python -m archinstall --config <local path or remote URL> + ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| Key | Values/Description | Description | Required | +| | | | | ++======================+========================================================+============================================================================+===============================================+ +| audio | pipewire/pulseaudio | Audioserver to be installed | No | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| bootloader | systemd-bootctl/grub-install | Bootloader to be installed | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| custom-commands | [ <command1>, <command2>, ...] | Custom commands to be run post install | No | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| !encryption-password | any | Password to encrypt disk, not encrypted if password not provided | No | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| filesystem | ext4 / btrfs / fat32 etc. | Filesystem for root and home partitions | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| harddrive | { "path": <path of device> } | Path of device to be used | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| hostname | any | Hostname of machine after installation | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| kernels | [ "kernel1", "kernel2"] | List of kernels to install eg: linux, linux-lts, linux-zen etc | Atleast 1 | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| keyboard-language | 2 letter code for your keyboard language | eg: us, de etc | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| mirror-region | {"<Region Name>": { "Mirror Name": True/False}, ..} | List of regions and mirrors to use | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| nic | nic to use, Use value NetworkManager for installing it | | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| packages | [ "package1", "package2", ..] | List of packages to install post-installation | No | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| profile | Name of profile to install | profiles are present in profiles/, use the name of a profile to install it | No | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| !root-password | any | The root account password | No | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| services | [ "service1", "service2", ..] | Services to enable post-installation | No | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| superusers | { "<username>": { "!password": "<password>"}, ..} | List of superuser credentials, see config for reference | Yes, if root account password is not provided | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| timezone | Timezone to configure in installation | Timezone eg: UTC, Asia/Kolkata etc. | Yes | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ +| users | { "<username>": { "!password": "<password>"}, ..} | List of regular user credentials, see config for reference | Yes, can be {} | ++----------------------+--------------------------------------------------------+----------------------------------------------------------------------------+-----------------------------------------------+ + Description individual steps ============================ @@ -173,4 +269,4 @@ After which you can press :code:`Enter` can be pressed in order to start the for Post installation ----------------- -Once the installation is complete, green text should appear saying that it's safe to `reboot`, which is also the command you use to reboot. +Once the installation is complete, green text should appear saying that it's safe to `reboot`, which is also the command you use to reboot.
\ No newline at end of file diff --git a/examples/custom-command-sample.json b/examples/custom-command-sample.json index 0518d3db..5e7a70e3 100644 --- a/examples/custom-command-sample.json +++ b/examples/custom-command-sample.json @@ -26,6 +26,7 @@ }, "packages": ["docker", "git", "wget", "zsh"], "profile": "gnome", + "services": ["docker"], "superusers": { "devel": { "!password": "devel" diff --git a/examples/guided.py b/examples/guided.py index 1e370e21..c31f170c 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -12,6 +12,9 @@ from archinstall.lib.profiles import Profile if archinstall.arguments.get('help'): print("See `man archinstall` for help.") exit(0) +if os.getuid() != 0: + print("Archinstall requires root privileges to run. See --help for more.") + exit(1) # For support reasons, we'll log the disk layout pre installation to match against post-installation layout archinstall.log(f"Disk states before installing: {archinstall.disk_layouts()}", level=logging.DEBUG) @@ -50,6 +53,16 @@ def ask_user_questions(): selected_region = archinstall.arguments['mirror-region'] archinstall.arguments['mirror-region'] = {selected_region: archinstall.list_mirrors()[selected_region]} + if not archinstall.arguments.get('sys-language', None) and archinstall.arguments.get('advanced', False): + archinstall.arguments['sys-language'] = input("Enter a valid locale (language) for your OS, (Default: en_US): ").strip() + archinstall.arguments['sys-encoding'] = input("Enter a valid system default encoding for your OS, (Default: utf-8): ").strip() + archinstall.log("Keep in mind that if you want multiple locales, post configuration is required.", fg="yellow") + + if not archinstall.arguments.get('sys-language', None): + archinstall.arguments['sys-language'] = 'en_US' + if not archinstall.arguments.get('sys-encoding', None): + archinstall.arguments['sys-encoding'] = 'utf-8' + # Ask which harddrives/block-devices we will install to # and convert them into archinstall.BlockDevice() objects. if archinstall.arguments.get('harddrives', None): @@ -103,7 +116,7 @@ def ask_user_questions(): # Ask for archinstall-specific profiles (such as desktop environments etc) if not archinstall.arguments.get('profile', None): - archinstall.arguments['profile'] = archinstall.select_profile(archinstall.list_profiles(filter_top_level_profiles=True)) + archinstall.arguments['profile'] = archinstall.select_profile() else: archinstall.arguments['profile'] = Profile(installer=None, path=archinstall.arguments['profile']) @@ -162,6 +175,12 @@ def ask_user_questions(): if not archinstall.arguments.get('timezone', None): archinstall.arguments['timezone'] = archinstall.ask_for_a_timezone() + if archinstall.arguments['timezone']: + if not archinstall.arguments.get('ntp', False): + archinstall.arguments['ntp'] = input("Would you like to use automatic time synchronization (NTP) with the default time servers? [Y/n]: ").strip().lower() in ('y', 'yes', '') + if archinstall.arguments['ntp']: + archinstall.log("Hardware time and other post-configuration steps might be required in order for NTP to work. For more information, please check the Arch wiki.", fg="yellow") + def perform_filesystem_operations(): print() @@ -247,6 +266,7 @@ def perform_installation(mountpoint): if archinstall.arguments.get('mirror-region', None): archinstall.use_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors for the live medium if installation.minimal_installation(): + installation.set_locale(archinstall.arguments['sys-language'], archinstall.arguments['sys-encoding'].upper()) installation.set_hostname(archinstall.arguments['hostname']) if archinstall.arguments['mirror-region'].get("mirrors", None) is not None: installation.set_mirrors(archinstall.arguments['mirror-region']) # Set the mirrors in the installation medium @@ -294,6 +314,9 @@ def perform_installation(mountpoint): if timezone := archinstall.arguments.get('timezone', None): installation.set_timezone(timezone) + if archinstall.arguments.get('ntp', False): + installation.activate_ntp() + if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw): installation.user_set_pw('root', root_pw) @@ -307,6 +330,11 @@ def perform_installation(mountpoint): archinstall.log(' * Profile\'s post configuration requirements was not fulfilled.', fg='red') exit(1) + # If the user provided a list of services to be enabled, pass the list to the enable_service function. + # Note that while it's called enable_service, it can actually take a list of services and iterate it. + if archinstall.arguments.get('services', None): + installation.enable_service(*archinstall.arguments['services']) + # If the user provided custom commands to be run post-installation, execute them now. if archinstall.arguments.get('custom-commands', None): run_custom_user_commands(archinstall.arguments['custom-commands'], installation) @@ -345,6 +373,11 @@ else: else: archinstall.arguments['profile'] = None -ask_user_questions() + if archinstall.arguments.get('mirror-region', None) is not None: + selected_region = archinstall.arguments.get('mirror-region', None) + archinstall.arguments['mirror-region'] = {selected_region: archinstall.list_mirrors()[selected_region]} + archinstall.arguments['sys-language'] = archinstall.arguments.get('sys-language', 'en_US') + archinstall.arguments['sys-encoding'] = archinstall.arguments.get('sys-encoding', 'utf-8') + perform_filesystem_operations() perform_installation(archinstall.arguments.get('target-mountpoint', None))
\ No newline at end of file |