Ejemplo n.º 1
0
def _prep_function(*args, **kwargs) -> bool:
    """
	Magic function called by the importing installer
	before continuing any further. It also avoids executing any
	other code in this stage. So it's a safe way to ask the user
	for more input before any other installer steps start.
	"""
    choice = Menu(str(_('Select your desired desktop environment')),
                  __supported__).run()

    if choice.type_ != MenuSelectionType.Selection:
        return False

    if choice.value:
        # Temporarily store the selected desktop profile
        # in a session-safe location, since this module will get reloaded
        # the next time it gets executed.
        if not archinstall.storage.get('_desktop_profile', None):
            archinstall.storage['_desktop_profile'] = choice.value
        if not archinstall.arguments.get('desktop-environment', None):
            archinstall.arguments['desktop-environment'] = choice.value
        profile = archinstall.Profile(None, choice.value)
        # Loading the instructions with a custom namespace, ensures that a __name__ comparison is never triggered.
        with profile.load_instructions(
                namespace=f"{choice.value}.py") as imported:
            if hasattr(imported, '_prep_function'):
                return imported._prep_function()
            else:
                log(f"Deprecated (??): {choice.value} profile has no _prep_function() anymore"
                    )
                exit(1)

    return False
Ejemplo n.º 2
0
def perform_installation(mountpoint, mode):
	"""
	Performs the installation steps on a block device.
	Only requirement is that the block devices are
	formatted and setup prior to entering this function.
	"""
	with archinstall.Installer(mountpoint, kernels=archinstall.arguments.get('kernels', ['linux'])) as installation:
		if mode in ('full','only_hd'):
			disk_setup(installation)
			if mode == 'only_hd':
				target = pathlib.Path(f"{mountpoint}/etc/fstab")
				if not target.parent.exists():
					target.parent.mkdir(parents=True)

		if mode in ('full','only_os'):
			os_setup(installation)
			installation.log("For post-installation tips, see https://wiki.archlinux.org/index.php/Installation_guide#Post-installation", fg="yellow")
			if not archinstall.arguments.get('silent'):
				prompt = 'Would you like to chroot into the newly created installation and perform post-installation configuration?'
				choice = Menu(prompt, Menu.yes_no(), default_option=Menu.yes()).run()
				if choice == Menu.yes():
					try:
						installation.drop_to_shell()
					except:
						pass

	# For support reasons, we'll log the disk layout post installation (crash or no crash)
	archinstall.log(f"Disk states after installing: {archinstall.disk_layouts()}", level=logging.DEBUG)
Ejemplo n.º 3
0
def perform_installation(mountpoint):
    """
	Performs the installation steps on a block device.
	Only requirement is that the block devices are
	formatted and setup prior to entering this function.
	"""
    with archinstall.Installer(mountpoint, kernels=None) as installation:
        # Mount all the drives to the desired mountpoint
        # This *can* be done outside of the installation, but the installer can deal with it.
        if archinstall.storage.get('disk_layouts'):
            installation.mount_ordered_layout(
                archinstall.storage['disk_layouts'])

        # Placing /boot check during installation because this will catch both re-use and wipe scenarios.
        for partition in installation.partitions:
            if partition.mountpoint == installation.target + '/boot':
                if partition.size <= 0.25:  # in GB
                    raise archinstall.DiskError(
                        f"The selected /boot partition in use is not large enough to properly install a boot loader. Please resize it to at least 256MB and re-run the installation."
                    )
        # to generate a fstab directory holder. Avoids an error on exit and at the same time checks the procedure
        target = pathlib.Path(f"{mountpoint}/etc/fstab")
        if not target.parent.exists():
            target.parent.mkdir(parents=True)

    # For support reasons, we'll log the disk layout post installation (crash or no crash)
    archinstall.log(
        f"Disk states after installing: {archinstall.disk_layouts()}",
        level=logging.DEBUG)
Ejemplo n.º 4
0
	def _select_profile(self):
		profile = archinstall.select_profile()

		# Check the potentially selected profiles preparations to get early checks if some additional questions are needed.
		if profile and profile.has_prep_function():
			namespace = f'{profile.namespace}.py'
			with profile.load_instructions(namespace=namespace) as imported:
				if not imported._prep_function():
					archinstall.log(' * Profile\'s preparation requirements was not fulfilled.', fg='red')
					exit(1)

		return profile
Ejemplo n.º 5
0
	def _setup_selection_menu_options(self):
		super()._setup_selection_menu_options()
		options_list = []
		mandatory_list = []
		if self._execution_mode in ('full','lineal'):
			options_list = ['keyboard-layout', 'mirror-region', 'harddrives', 'disk_layouts',
					'!encryption-password','swap', 'bootloader', 'hostname', '!root-password',
					'!superusers', '!users', 'profile', 'audio', 'kernels', 'packages','additional-repositories','nic',
					'timezone', 'ntp']
			if archinstall.arguments.get('advanced',False):
				options_list.extend(['sys-language','sys-encoding'])
			mandatory_list = ['harddrives','bootloader','hostname']
		elif self._execution_mode == 'only_hd':
			options_list = ['harddrives', 'disk_layouts', '!encryption-password','swap']
			mandatory_list = ['harddrives']
		elif self._execution_mode == 'only_os':
			options_list = ['keyboard-layout', 'mirror-region','bootloader', 'hostname',
					'!root-password', '!superusers', '!users', 'profile', 'audio', 'kernels',
					'packages', 'additional-repositories', 'nic', 'timezone', 'ntp']
			mandatory_list = ['hostname']
			if archinstall.arguments.get('advanced',False):
				options_list.expand(['sys-language','sys-encoding'])
		elif self._execution_mode == 'minimal':
			pass
		else:
			archinstall.log(f"self._execution_mode {self._execution_mode} not supported")
			exit(1)
		if self._execution_mode != 'lineal':
			options_list.extend(['save_config','install','abort'])
			if not archinstall.arguments.get('advanced'):
				options_list.append('archinstall-language')

		for entry in self._menu_options:
			if entry in options_list:
				# for not lineal executions, only self.option(entry).set_enabled and set_mandatory are necessary
				if entry in mandatory_list:
					self.enable(entry,mandatory=True)
				else:
					self.enable(entry)
			else:
				self.option(entry).set_enabled(False)
		self._update_install_text()
Ejemplo n.º 6
0
def ask_user_questions(mode):
	"""
		First, we'll ask the user for a bunch of user input.
		Not until we're satisfied with what we want to install
		will we continue with the actual installation steps.
	"""
	if archinstall.arguments.get('advanced',None):
		# 3.9 syntax. former x = {**y,**z} or x.update(y)
		set_cmd_locale(charset='es_ES.utf8',collate='es_ES.utf8')
		setup_area = archinstall.storage.get('CMD_LOCALE',{}) | {}
		with SetupMenu(setup_area) as setup:
			if mode == 'lineal':
				for entry in setup.list_enabled_options():
					if entry in ('continue','abort'):
						continue
					if not setup.option(entry).enabled:
						continue
					setup.exec_option(entry)
			else:
				setup.run()
		archinstall.arguments['archinstall-language'] = setup_area.get('archinstall-language')
	else:
		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")
		archinstall.SysCommand('timedatectl set-ntp true')

	with MyMenu(data_store=archinstall.arguments,mode=mode) as global_menu:

		if mode == 'lineal':
			for entry in global_menu.list_enabled_options():
				if entry in ('install','abort'):
					continue
				global_menu.exec_option(entry)
				archinstall.arguments[entry] = global_menu.option(entry).get_selection()
		else:
			global_menu.set_option('install',
							archinstall.Selector(
								global_menu._install_text(mode),
								exec_func=lambda n,v: True if global_menu._missing_configs(mode) == 0 else False,
								enabled=True))

			global_menu.run()
Ejemplo n.º 7
0
def perform_installation_steps():
	print()
	print('This is your chosen configuration:')
	archinstall.log("-- Guided template chosen (with below config) --", level=archinstall.LOG_LEVELS.Debug)
	archinstall.log(json.dumps(archinstall.arguments, indent=4, sort_keys=True, cls=archinstall.JSON), level=archinstall.LOG_LEVELS.Info)
	print()

	input('Press Enter to continue.')

	"""
		Issue a final warning before we continue with something un-revertable.
		We mention the drive one last time, and count from 5 to 0.
	"""

	if archinstall.arguments.get('harddrive', None):
		print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='')
		archinstall.do_countdown()

		"""
			Setup the blockdevice, filesystem (and optionally encryption).
			Once that's done, we'll hand over to perform_installation()
		"""
		with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs:
			# Wipe the entire drive if the disk flag `keep_partitions`is False.
			if archinstall.arguments['harddrive'].keep_partitions is False:
				fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs'))
			
			# Check if encryption is desired and mark the root partition as encrypted.
			if archinstall.arguments.get('!encryption-password', None):
				root_partition = fs.find_partition('/')
				root_partition.encrypted = True
					
			# After the disk is ready, iterate the partitions and check
			# which ones are safe to format, and format those.
			for partition in archinstall.arguments['harddrive']:
				if partition.safe_to_format():
					# Partition might be marked as encrypted due to the filesystem type crypt_LUKS
					# But we might have omitted the encryption password question to skip encryption.
					# In which case partition.encrypted will be true, but passwd will be false.
					if partition.encrypted and (passwd := archinstall.arguments.get('!encryption-password', None)):
						partition.encrypt(password=passwd)
					else:
						partition.format()
				else:
					archinstall.log(f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.", level=archinstall.LOG_LEVELS.Debug)

			fs.find_partition('/boot').format('vfat')

			if archinstall.arguments.get('!encryption-password', None):
				# First encrypt and unlock, then format the desired partition inside the encrypted part.
				# archinstall.luks2() encrypts the partition when entering the with context manager, and
				# unlocks the drive so that it can be used as a normal block-device within archinstall.
				with archinstall.luks2(fs.find_partition('/'), 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_device:
					unlocked_device.format(fs.find_partition('/').filesystem)
					unlocked_device.mount('/mnt')
			else:
				fs.find_partition('/').format(fs.find_partition('/').filesystem)
				fs.find_partition('/').mount('/mnt')

			fs.find_partition('/boot').mount('/mnt/boot')
Ejemplo n.º 8
0
def write_config_files():
    print()
    print('This is your chosen configuration:')
    archinstall.log("-- Guided template chosen (with below config) --",
                    level=logging.DEBUG)

    user_configuration = json.dumps(
        {
            **archinstall.arguments, 'version': archinstall.__version__
        },
        indent=4,
        sort_keys=True,
        cls=archinstall.JSON)
    archinstall.log(user_configuration, level=logging.INFO)

    if archinstall.storage.get('disk_layouts'):
        user_disk_layout = json.dumps(archinstall.storage['disk_layouts'],
                                      indent=4,
                                      sort_keys=True,
                                      cls=archinstall.JSON)
        archinstall.log(user_disk_layout, level=logging.INFO)

    print()

    save_user_configurations()
    if archinstall.arguments.get('dry-run'):
        exit(0)
Ejemplo n.º 9
0
def install_on(mountpoint):
    # We kick off the installer by telling it where the
    with archinstall.Installer(mountpoint) as installation:
        # Strap in the base system, add a boot loader and configure
        # some other minor details as specified by this profile and user.
        if installation.minimal_installation():
            installation.set_hostname('minimal-arch')
            installation.add_bootloader()

            # Optionally enable networking:
            if archinstall.arguments.get('network', None):
                installation.copy_ISO_network_config(enable_services=True)

            installation.add_additional_packages(['nano', 'wget', 'git'])
            installation.install_profile('minimal')

            installation.user_create('devel', 'devel')
            installation.user_set_pw('root', 'airoot')

    # Once this is done, we output some useful information to the user
    # And the installation is complete.
    archinstall.log(
        f"There are two new accounts in your installation after reboot:")
    archinstall.log(f" * root (password: airoot)")
    archinstall.log(f" * devel (password: devel)")
Ejemplo n.º 10
0
def perform_installation(device, boot_partition, language, mirrors):
	"""
	Performs the installation steps on a block device.
	Only requirement is that the block devices are
	formatted and setup prior to entering this function.
	"""
	with archinstall.Installer(device, boot_partition=boot_partition, hostname=hostname) as installation:
		## if len(mirrors):
		# Certain services might be running that affects the system during installation.
		# Currently, only one such service is "reflector.service" which updates /etc/pacman.d/mirrorlist
		# We need to wait for it before we continue since we opted in to use a custom mirror/region.
		archinstall.log(f'Waiting for automatic mirror selection has completed before using custom mirrors.')
		while 'dead' not in (status := archinstall.service_state('reflector')):
			time.sleep(1)

		archinstall.use_mirrors(mirrors) # Set the mirrors for the live medium
		if installation.minimal_installation():
			installation.set_mirrors(mirrors) # Set the mirrors in the installation medium
			installation.set_keyboard_language(language)
			installation.add_bootloader()

			if len(packages) and packages[0] != '':
				installation.add_additional_packages(packages)

			if len(profile.strip()):
				installation.install_profile(profile)

			for user, password in users.items():
				sudo = False
				if len(root_pw.strip()) == 0:
					sudo = True

				installation.user_create(user, password, sudo=sudo)

			if root_pw:
				installation.user_set_pw('root', root_pw)
Ejemplo n.º 11
0
def ask_user_questions():
    """
        First, we'll ask the user for a bunch of user input.
        Not until we're satisfied with what we want to install
        will we continue with the actual installation steps.
    """
    if not archinstall.arguments.get('keyboard-layout', None):
        while True:
            try:
                archinstall.arguments['keyboard-layout'] = archinstall.select_language(archinstall.list_keyboard_languages()).strip()
                break
            except archinstall.RequirementError as err:
                archinstall.log(err, fg="red")

    # Before continuing, set the preferred keyboard layout/language in the current terminal.
    # This will just help the user with the next following questions.
    if len(archinstall.arguments['keyboard-layout']):
        archinstall.set_keyboard_language(archinstall.arguments['keyboard-layout'])

    # Set which region to download packages from during the installation
    if not archinstall.arguments.get('mirror-region', None):
        while True:
            try:
                archinstall.arguments['mirror-region'] = archinstall.select_mirror_regions(archinstall.list_mirrors())
                break
            except archinstall.RequirementError as e:
                archinstall.log(e, fg="red")

    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) is None:
        _prompt = "Select one or more harddrives to use and configure (leave blank to skip this step): "
        archinstall.arguments['harddrives'] = archinstall.generic_multi_select(archinstall.all_disks(), text=_prompt, allow_empty=True)

    if archinstall.arguments.get('harddrives', None) is not None and archinstall.storage.get('disk_layouts', None) is None:
        archinstall.storage['disk_layouts'] = archinstall.select_disk_layout(archinstall.arguments['harddrives'], archinstall.arguments.get('advanced', False))

    # Get disk encryption password (or skip if blank)
    if archinstall.arguments['harddrives'] and archinstall.arguments.get('!encryption-password', None) is None:
        if passwd := archinstall.get_password(prompt='Enter disk encryption password (leave blank for no encryption): '):
            archinstall.arguments['!encryption-password'] = passwd
Ejemplo n.º 12
0
def perform_filesystem_operations():
    print()
    print('This is your chosen configuration:')
    archinstall.log("-- Guided template chosen (with below config) --",
                    level=logging.DEBUG)

    user_configuration = json.dumps(
        {
            **archinstall.arguments, 'version': archinstall.__version__
        },
        indent=4,
        sort_keys=True,
        cls=archinstall.JSON)
    archinstall.log(user_configuration, level=logging.INFO)

    if archinstall.arguments.get('disk_layouts'):
        user_disk_layout = json.dumps(archinstall.arguments['disk_layouts'],
                                      indent=4,
                                      sort_keys=True,
                                      cls=archinstall.JSON)
        archinstall.log(user_disk_layout, level=logging.INFO)

    print()

    if archinstall.arguments.get('dry_run'):
        exit(0)

    if not archinstall.arguments.get('silent'):
        input('Press Enter to continue.')
    """
		Issue a final warning before we continue with something un-revertable.
		We mention the drive one last time, and count from 5 to 0.
	"""

    if archinstall.arguments.get('harddrives', None):
        print(f" ! Formatting {archinstall.arguments['harddrives']} in ",
              end='')
        archinstall.do_countdown()
        """
			Setup the blockdevice, filesystem (and optionally encryption).
			Once that's done, we'll hand over to perform_installation()
		"""
        mode = archinstall.GPT
        if archinstall.has_uefi() is False:
            mode = archinstall.MBR

        for drive in archinstall.arguments.get('harddrives', []):
            if archinstall.arguments.get('disk_layouts', {}).get(drive.path):
                with archinstall.Filesystem(drive, mode) as fs:
                    fs.load_layout(
                        archinstall.arguments['disk_layouts'][drive.path])
Ejemplo n.º 13
0
def ask_harddrives():
    # Ask which harddrives/block-devices we will install to
    # and convert them into archinstall.BlockDevice() objects.
    if archinstall.arguments.get('harddrives', None) is None:
        archinstall.arguments['harddrives'] = archinstall.generic_multi_select(
            archinstall.all_disks(),
            text=
            "Select one or more harddrives to use and configure (leave blank to skip this step): ",
            allow_empty=True)

    if not archinstall.arguments['harddrives']:
        archinstall.log("You decided to skip harddrive selection",
                        fg="red",
                        level=logging.INFO)
        archinstall.log(
            f"and will use whatever drive-setup is mounted at {archinstall.storage['MOUNT_POINT']} (experimental)",
            fg="red",
            level=logging.INFO)
        archinstall.log(
            "WARNING: Archinstall won't check the suitability of this setup",
            fg="red",
            level=logging.INFO)
        if input("Do you wish to continue ? [Y/n]").strip().lower() == 'n':
            exit(1)
    else:
        if archinstall.storage.get('disk_layouts', None) is None:
            archinstall.storage[
                'disk_layouts'] = archinstall.select_disk_layout(
                    archinstall.arguments['harddrives'],
                    archinstall.arguments.get('advanced', False))

        # Get disk encryption password (or skip if blank)
        if archinstall.arguments.get('!encryption-password', None) is None:
            if passwd := archinstall.get_password(
                    prompt=
                    'Enter disk encryption password (leave blank for no encryption): '
            ):
                archinstall.arguments['!encryption-password'] = passwd

        if archinstall.arguments.get('!encryption-password', None):
            # If no partitions was marked as encrypted, but a password was supplied and we have some disks to format..
            # Then we need to identify which partitions to encrypt. This will default to / (root).
            if len(
                    list(
                        archinstall.encrypted_partitions(
                            archinstall.storage['disk_layouts']))) == 0:
                archinstall.storage[
                    'disk_layouts'] = archinstall.select_encrypted_partitions(
                        archinstall.storage['disk_layouts'],
                        archinstall.arguments['!encryption-password'])
Ejemplo n.º 14
0
	def exit_callback(self):
		if self._data_store.get('ntp',False):
			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")
			archinstall.SysCommand('timedatectl set-ntp true')
		if self._data_store.get('mode',None):
			archinstall.arguments['mode'] = self._data_store['mode']
			archinstall.log(f"Archinstall will execute under {archinstall.arguments['mode']} mode")
		if self._data_store.get('LC_ALL',None):
			archinstall.storage['CMD_LOCALE'] = {'LC_ALL':self._data_store['LC_ALL']}
		else:
			exec_locale = {}
			for item in ['LC_COLLATE','LC_CTYPE','LC_MESSAGES','LC_NUMERIC','LC_TIME']:
				if self._data_store.get(item,None):
					exec_locale[item] = self._data_store[item]
			archinstall.storage['CMD_LOCALE'] = exec_locale
		archinstall.log(f"Archinstall will execute with {archinstall.storage.get('CMD_LOCALE',None)} locale")
Ejemplo n.º 15
0
def write_config_files():
    print()
    print('This is your chosen configuration:')
    archinstall.log("-- Guided template chosen (with below config) --",
                    level=logging.DEBUG)
    user_configuration = json.dumps(archinstall.arguments,
                                    indent=4,
                                    sort_keys=True,
                                    cls=archinstall.JSON)
    archinstall.log(user_configuration, level=logging.INFO)
    with open("/var/log/archinstall/user_configuration.json",
              "w") as config_file:
        config_file.write(user_configuration)
    if archinstall.storage.get('disk_layouts'):
        user_disk_layout = json.dumps(archinstall.storage['disk_layouts'],
                                      indent=4,
                                      sort_keys=True,
                                      cls=archinstall.JSON)
        archinstall.log(user_disk_layout, level=logging.INFO)
        with open("/var/log/archinstall/user_disk_layout.json",
                  "w") as disk_layout_file:
            disk_layout_file.write(user_disk_layout)
    print()

    if archinstall.arguments.get('dry-run'):
        exit(0)

    # it is here so a dry run execution will not save the credentials file ¿?
    user_credentials = {}
    if archinstall.arguments.get('!users'):
        user_credentials["!users"] = archinstall.arguments['!users']
    if archinstall.arguments.get('!superusers'):
        user_credentials["!superusers"] = archinstall.arguments['!superusers']
    if archinstall.arguments.get('!encryption-password'):
        user_credentials["!encryption-password"] = archinstall.arguments[
            '!encryption-password']

    with open("/var/log/archinstall/user_credentials.json",
              "w") as config_file:
        config_file.write(
            json.dumps(user_credentials,
                       indent=4,
                       sort_keys=True,
                       cls=archinstall.UNSAFE_JSON))
Ejemplo n.º 16
0
import archinstall

# Select a harddrive and a disk password
archinstall.log(f"Minimal only supports:")
archinstall.log(f" * Being installed to a single disk")

if archinstall.arguments.get('help', None):
    archinstall.log(
        f" - Optional disk encryption via --!encryption-password=<password>")
    archinstall.log(f" - Optional filesystem type via --filesystem=<fs type>")
    archinstall.log(f" - Optional systemd network via --network")

archinstall.arguments['harddrive'] = archinstall.select_disk(
    archinstall.all_disks())


def install_on(mountpoint):
    # We kick off the installer by telling it where the
    with archinstall.Installer(mountpoint) as installation:
        # Strap in the base system, add a boot loader and configure
        # some other minor details as specified by this profile and user.
        if installation.minimal_installation():
            installation.set_hostname('minimal-arch')
            installation.add_bootloader()

            # Optionally enable networking:
            if archinstall.arguments.get('network', None):
                installation.copy_ISO_network_config(enable_services=True)

            installation.add_additional_packages(['nano', 'wget', 'git'])
            installation.install_profile('minimal')
Ejemplo n.º 17
0
	before continuing any further.
	"""
    if not archinstall.storage.get('_selected_servers', None):
        servers = archinstall.Menu(
            'Choose which servers to install, if none then a minimal installation wil be done',
            available_servers,
            multi=True).run()

        archinstall.storage['_selected_servers'] = servers

    return True


if __name__ == 'server':
    """
	This "profile" is a meta-profile.
	"""
    archinstall.log('Now installing the selected servers.', level=logging.INFO)
    archinstall.log(archinstall.storage['_selected_servers'],
                    level=logging.DEBUG)
    for server in archinstall.storage['_selected_servers']:
        archinstall.log(f'Installing {server} ...', level=logging.INFO)
        app = archinstall.Application(
            archinstall.storage['installation_session'], server)
        app.install()

    archinstall.log(
        'If your selections included multiple servers with the same port, you may have to reconfigure them.',
        fg="yellow",
        level=logging.INFO)
Ejemplo n.º 18
0
import archinstall
import logging

# Define the package list in order for lib to source
# which packages will be installed by this profile
__packages__ = [
    "pipewire", "pipewire-alsa", "pipewire-jack", "pipewire-pulse",
    "gst-plugin-pipewire", "libpulse", "wireplumber"
]

archinstall.log('Installing pipewire', level=logging.INFO)
archinstall.storage['installation_session'].add_additional_packages(
    __packages__)


@archinstall.plugin
def on_user_created(installation: archinstall.Installer, user: str):
    archinstall.log(f"Enabling pipewire-pulse for {user}", level=logging.INFO)
    installation.chroot('systemctl enable --user pipewire-pulse.service',
                        run_as=user)
Ejemplo n.º 19
0
def on_user_created(installation: archinstall.Installer, user: str):
    archinstall.log(f"Enabling pipewire-pulse for {user}", level=logging.INFO)
    installation.chroot('systemctl enable --user pipewire-pulse.service',
                        run_as=user)
Ejemplo n.º 20
0
def ask_user_questions():
    """
	  First, we'll ask the user for a bunch of user input.
	  Not until we're satisfied with what we want to install
	  will we continue with the actual installation steps.
	"""
    if not archinstall.arguments.get('keyboard-language', None):
        archinstall.arguments[
            'keyboard-language'] = archinstall.select_language(
                archinstall.list_keyboard_languages()).strip()

    # Before continuing, set the preferred keyboard layout/language in the current terminal.
    # This will just help the user with the next following questions.
    if len(archinstall.arguments['keyboard-language']):
        archinstall.set_keyboard_language(
            archinstall.arguments['keyboard-language'])

    # Set which region to download packages from during the installation
    if not archinstall.arguments.get('mirror-region', None):
        archinstall.arguments[
            'mirror-region'] = archinstall.select_mirror_regions(
                archinstall.list_mirrors())
    else:
        selected_region = archinstall.arguments['mirror-region']
        archinstall.arguments['mirror-region'] = {
            selected_region: archinstall.list_mirrors()[selected_region]
        }

    # Ask which harddrive/block-device we will install to
    if archinstall.arguments.get('harddrive', None):
        archinstall.arguments['harddrive'] = archinstall.BlockDevice(
            archinstall.arguments['harddrive'])
    else:
        archinstall.arguments['harddrive'] = archinstall.select_disk(
            archinstall.all_disks())

    # Perform a quick sanity check on the selected harddrive.
    # 1. Check if it has partitions
    # 3. Check that we support the current partitions
    # 2. If so, ask if we should keep them or wipe everything
    if archinstall.arguments['harddrive'].has_partitions():
        archinstall.log(
            f"{archinstall.arguments['harddrive']} contains the following partitions:",
            fg='yellow')

        # We curate a list pf supported paritions
        # and print those that we don't support.
        partition_mountpoints = {}
        for partition in archinstall.arguments['harddrive']:
            try:
                if partition.filesystem_supported():
                    archinstall.log(f" {partition}")
                    partition_mountpoints[partition] = None
            except archinstall.UnknownFilesystemFormat as err:
                archinstall.log(f" {partition} (Filesystem not supported)",
                                fg='red')

        # We then ask what to do with the paritions.
        if (option := archinstall.ask_for_disk_layout()) == 'abort':
            archinstall.log(
                f"Safely aborting the installation. No changes to the disk or system has been made."
            )
            exit(1)
        elif option == 'keep-existing':
            archinstall.arguments['harddrive'].keep_partitions = True

            archinstall.log(
                f" ** You will now select which partitions to use by selecting mount points (inside the installation). **"
            )
            archinstall.log(
                f" ** The root would be a simple / and the boot partition /boot (as all paths are relative inside the installation). **"
            )
            while True:
                # Select a partition
                partition = archinstall.generic_select(
                    partition_mountpoints.keys(),
                    "Select a partition by number that you want to set a mount-point for (leave blank when done): "
                )
                if not partition:
                    break

                # Select a mount-point
                mountpoint = input(
                    f"Enter a mount-point for {partition}: ").strip(' ')
                if len(mountpoint):

                    # Get a valid & supported filesystem for the parition:
                    while 1:
                        new_filesystem = input(
                            f"Enter a valid filesystem for {partition} (leave blank for {partition.filesystem}): "
                        ).strip(' ')
                        if len(new_filesystem) <= 0:
                            if partition.encrypted and partition.filesystem == 'crypto_LUKS':
                                old_password = archinstall.arguments.get(
                                    '!encryption-password', None)
                                if not old_password:
                                    old_password = input(
                                        f'Enter the old encryption password for {partition}: '
                                    )

                                if (autodetected_filesystem :=
                                        partition.detect_inner_filesystem(
                                            old_password)):
                                    new_filesystem = autodetected_filesystem
                                else:
                                    archinstall.log(
                                        f"Could not auto-detect the filesystem inside the encrypted volume.",
                                        fg='red')
                                    archinstall.log(
                                        f"A filesystem must be defined for the unlocked encrypted partition."
                                    )
                                    continue
                            break

                        # Since the potentially new filesystem is new
                        # we have to check if we support it. We can do this by formatting /dev/null with the partitions filesystem.
                        # There's a nice wrapper for this on the partition object itself that supports a path-override during .format()
                        try:
                            partition.format(new_filesystem,
                                             path='/dev/null',
                                             log_formating=False,
                                             allow_formatting=True)
                        except archinstall.UnknownFilesystemFormat:
                            archinstall.log(
                                f"Selected filesystem is not supported yet. If you want archinstall to support '{new_filesystem}', please create a issue-ticket suggesting it on github at https://github.com/Torxed/archinstall/issues."
                            )
                            archinstall.log(
                                f"Until then, please enter another supported filesystem."
                            )
                            continue
                        except archinstall.SysCallError:
                            pass  # Expected exception since mkfs.<format> can not format /dev/null.
                            # But that means our .format() function supported it.
                        break

                    # When we've selected all three criterias,
                    # We can safely mark the partition for formatting and where to mount it.
                    # TODO: allow_formatting might be redundant since target_mountpoint should only be
                    #       set if we actually want to format it anyway.
                    partition.allow_formatting = True
                    partition.target_mountpoint = mountpoint
                    # Only overwrite the filesystem definition if we selected one:
                    if len(new_filesystem):
                        partition.filesystem = new_filesystem

            archinstall.log('Using existing partition table reported above.')
Ejemplo n.º 21
0
def perform_installation_steps():
    global SIG_TRIGGER

    print()
    print('This is your chosen configuration:')
    archinstall.log("-- Guided template chosen (with below config) --",
                    level=archinstall.LOG_LEVELS.Debug)
    archinstall.log(json.dumps(archinstall.arguments,
                               indent=4,
                               sort_keys=True,
                               cls=archinstall.JSON),
                    level=archinstall.LOG_LEVELS.Info)
    print()

    input('Press Enter to continue.')
    """
		Issue a final warning before we continue with something un-revertable.
		We mention the drive one last time, and count from 5 to 0.
	"""

    print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='')

    for i in range(5, 0, -1):
        print(f"{i}", end='')

        for x in range(4):
            sys.stdout.flush()
            time.sleep(0.25)
            print(".", end='')

        if SIG_TRIGGER:
            abort = input('\nDo you really want to abort (y/n)? ')
            if abort.strip() != 'n':
                exit(0)

            if SIG_TRIGGER is False:
                sys.stdin.read()
            SIG_TRIGGER = False
            signal.signal(signal.SIGINT, sig_handler)

    # Put back the default/original signal handler now that we're done catching
    # and interrupting SIGINT with "Do you really want to abort".
    print()
    signal.signal(signal.SIGINT, original_sigint_handler)
    """
		Setup the blockdevice, filesystem (and optionally encryption).
		Once that's done, we'll hand over to perform_installation()
	"""
    with archinstall.Filesystem(archinstall.arguments['harddrive'],
                                archinstall.GPT) as fs:
        # Wipe the entire drive if the disk flag `keep_partitions`is False.
        if archinstall.arguments['harddrive'].keep_partitions is False:
            fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get(
                'filesystem', 'btrfs'))

        # Check if encryption is desired and mark the root partition as encrypted.
        if archinstall.arguments.get('!encryption-password', None):
            root_partition = fs.find_partition('/')
            root_partition.encrypted = True

        # After the disk is ready, iterate the partitions and check
        # which ones are safe to format, and format those.
        for partition in archinstall.arguments['harddrive']:
            if partition.safe_to_format():
                # Partition might be marked as encrypted due to the filesystem type crypt_LUKS
                # But we might have omitted the encryption password question to skip encryption.
                # In which case partition.encrypted will be true, but passwd will be false.
                if partition.encrypted and (passwd :=
                                            archinstall.arguments.get(
                                                '!encryption-password', None)):
                    partition.encrypt(password=passwd)
                else:
                    partition.format()
            else:
                archinstall.log(
                    f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.",
                    level=archinstall.LOG_LEVELS.Debug)

        if archinstall.arguments.get('!encryption-password', None):
            # First encrypt and unlock, then format the desired partition inside the encrypted part.
            # archinstall.luks2() encrypts the partition when entering the with context manager, and
            # unlocks the drive so that it can be used as a normal block-device within archinstall.
            with archinstall.luks2(
                    fs.find_partition('/'), 'luksloop',
                    archinstall.arguments.get('!encryption-password',
                                              None)) as unlocked_device:
                unlocked_device.format(fs.find_partition('/').filesystem)

                perform_installation(
                    device=unlocked_device,
                    boot_partition=fs.find_partition('/boot'),
                    language=archinstall.arguments['keyboard-language'],
                    mirrors=archinstall.arguments['mirror-region'])
        else:
            perform_installation(
                device=fs.find_partition('/'),
                boot_partition=fs.find_partition('/boot'),
                language=archinstall.arguments['keyboard-language'],
                mirrors=archinstall.arguments['mirror-region'])
Ejemplo n.º 22
0
def perform_installation(mountpoint):
    """
	Performs the installation steps on a block device.
	Only requirement is that the block devices are
	formatted and setup prior to entering this function.
	"""
    with archinstall.Installer(mountpoint,
                               kernels=archinstall.arguments.get(
                                   'kernels', 'linux')) as installation:
        # if len(mirrors):
        # Certain services might be running that affects the system during installation.
        # Currently, only one such service is "reflector.service" which updates /etc/pacman.d/mirrorlist
        # We need to wait for it before we continue since we opted in to use a custom mirror/region.
        installation.log(
            'Waiting for automatic mirror selection (reflector) to complete.',
            level=logging.INFO)
        while archinstall.service_state('reflector') not in ('dead', 'failed'):
            time.sleep(1)
        # Set mirrors used by pacstrap (outside of installation)
        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_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
            if archinstall.arguments[
                    "bootloader"] == "grub-install" and has_uefi():
                installation.add_additional_packages("grub")
            installation.add_bootloader(archinstall.arguments["bootloader"])

            # If user selected to copy the current ISO network configuration
            # Perform a copy of the config
            if archinstall.arguments.get(
                    'nic',
                {}) == 'Copy ISO network configuration to installation':
                installation.copy_iso_network_config(
                    enable_services=True
                )  # Sources the ISO network configuration to the install medium.
            elif archinstall.arguments.get('nic',
                                           {}).get('NetworkManager', False):
                installation.add_additional_packages("networkmanager")
                installation.enable_service('NetworkManager.service')
            # Otherwise, if a interface was selected, configure that interface
            elif archinstall.arguments.get('nic', {}):
                installation.configure_nic(
                    **archinstall.arguments.get('nic', {}))
                installation.enable_service('systemd-networkd')
                installation.enable_service('systemd-resolved')

            if archinstall.arguments.get('audio', None) is not None:
                installation.log(
                    f"This audio server will be used: {archinstall.arguments.get('audio', None)}",
                    level=logging.INFO)
                if archinstall.arguments.get('audio', None) == 'pipewire':
                    print('Installing pipewire ...')

                    installation.add_additional_packages([
                        "pipewire", "pipewire-alsa", "pipewire-jack",
                        "pipewire-media-session", "pipewire-pulse",
                        "gst-plugin-pipewire", "libpulse"
                    ])
                elif archinstall.arguments.get('audio', None) == 'pulseaudio':
                    print('Installing pulseaudio ...')
                    installation.add_additional_packages("pulseaudio")
            else:
                installation.log("No audio server will be installed.",
                                 level=logging.INFO)

            if archinstall.arguments.get('packages',
                                         None) and archinstall.arguments.get(
                                             'packages', None)[0] != '':
                installation.add_additional_packages(
                    archinstall.arguments.get('packages', None))

            if archinstall.arguments.get('profile', None):
                installation.install_profile(
                    archinstall.arguments.get('profile', None))

            for user, user_info in archinstall.arguments.get('users',
                                                             {}).items():
                installation.user_create(user,
                                         user_info["!password"],
                                         sudo=False)

            for superuser, user_info in archinstall.arguments.get(
                    'superusers', {}).items():
                installation.user_create(superuser,
                                         user_info["!password"],
                                         sudo=True)

            if timezone := archinstall.arguments.get('timezone', None):
                installation.set_timezone(timezone)

            if (root_pw := archinstall.arguments.get('!root-password',
                                                     None)) and len(root_pw):
                installation.user_set_pw('root', root_pw)

            # This step must be after profile installs to allow profiles to install language pre-requisits.
            # After which, this step will set the language both for console and x11 if x11 was installed for instance.
            installation.set_keyboard_language(
                archinstall.arguments['keyboard-language'])

            if archinstall.arguments['profile'] and archinstall.arguments[
                    'profile'].has_post_install():
                with archinstall.arguments['profile'].load_instructions(
                        namespace=
                        f"{archinstall.arguments['profile'].namespace}.py"
                ) as imported:
                    if not imported._post_install():
                        archinstall.log(
                            ' * Profile\'s post configuration requirements was not fulfilled.',
                            fg='red')
                        exit(1)
Ejemplo n.º 23
0
    if not archinstall.arguments.get('profile', None):
        archinstall.arguments['profile'] = archinstall.select_profile(
            archinstall.list_profiles())
    else:
        archinstall.arguments['profile'] = archinstall.list_profiles()[
            archinstall.arguments['profile']]

    # Check the potentially selected profiles preperations to get early checks if some additional questions are needed.
    if archinstall.arguments['profile'] and archinstall.arguments[
            'profile'].has_prep_function():
        with archinstall.arguments['profile'].load_instructions(
                namespace=f"{archinstall.arguments['profile'].namespace}.py"
        ) as imported:
            if not imported._prep_function():
                archinstall.log(
                    ' * Profile\'s preparation requirements was not fulfilled.',
                    bg='black',
                    fg='red')
                exit(1)

    # Additional packages (with some light weight error handling for invalid package names)
    if not archinstall.arguments.get('packages', None):
        archinstall.arguments['packages'] = [
            package for package in input(
                'Write additional packages to install (space separated, leave blank to skip): '
            ).split(' ') if len(package)
        ]

    # Verify packages that were given
    try:
        archinstall.validate_package_list(archinstall.arguments['packages'])
    except archinstall.RequirementError as e:
Ejemplo n.º 24
0
import archinstall
from archinstall.lib.general import run_custom_user_commands
from archinstall.lib.hardware import *
from archinstall.lib.networking import check_mirror_reachable
from archinstall.lib.profiles import Profile, is_desktop_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)

# Log various information about hardware before starting the installation. This might assist in troubleshooting
archinstall.log(
    f"Hardware model detected: {archinstall.sys_vendor()} {archinstall.product_name()}; UEFI mode: {archinstall.has_uefi()}",
    level=logging.DEBUG)
archinstall.log(f"Processor model detected: {archinstall.cpu_model()}",
                level=logging.DEBUG)
archinstall.log(
    f"Memory statistics: {archinstall.mem_available()} available out of {archinstall.mem_total()} total installed",
    level=logging.DEBUG)
archinstall.log(
    f"Virtualization detected: {archinstall.virtualization()}; is VM: {archinstall.is_vm()}",
    level=logging.DEBUG)
archinstall.log(
    f"Graphics devices detected: {archinstall.graphics_devices().keys()}",
    level=logging.DEBUG)

# 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()}",
Ejemplo n.º 25
0
import logging
import os
import time

import archinstall
from archinstall.lib.general import run_custom_user_commands
from archinstall.lib.hardware import has_uefi
from archinstall.lib.networking import check_mirror_reachable
from archinstall.lib.profiles import Profile

if archinstall.arguments.get('help'):
    print("See `man archinstall` for help.")
    exit(0)

# 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)


def ask_user_questions():
    """
		First, we'll ask the user for a bunch of user input.
		Not until we're satisfied with what we want to install
		will we continue with the actual installation steps.
	"""
    if not archinstall.arguments.get('keyboard-language', None):
        while True:
            try:
                archinstall.arguments[
                    'keyboard-language'] = archinstall.select_language(
                        archinstall.list_keyboard_languages()).strip()
                break
Ejemplo n.º 26
0
                lambda profile:
                (Profile(None, profile).is_top_level_profile()),
                archinstall.list_profiles()))
    else:
        archinstall.arguments['profile'] = archinstall.list_profiles()[
            archinstall.arguments['profile']]

    # Check the potentially selected profiles preparations to get early checks if some additional questions are needed.
    if archinstall.arguments['profile'] and archinstall.arguments[
            'profile'].has_prep_function():
        with archinstall.arguments['profile'].load_instructions(
                namespace=f"{archinstall.arguments['profile'].namespace}.py"
        ) as imported:
            if not imported._prep_function():
                archinstall.log(
                    ' * Profile\'s preparation requirements was not fulfilled.',
                    fg='red')
                exit(1)

    # Ask about audio server selection if one is not already set
    if not archinstall.arguments.get('audio', None):

        # only ask for audio server selection on a desktop profile
        if str(archinstall.arguments['profile']) == 'Profile(desktop)':
            archinstall.arguments[
                'audio'] = archinstall.ask_for_audio_selection()
        else:
            # packages installed by a profile may depend on audio and something may get installed anyways, not much we can do about that.
            # we will not try to remove packages post-installation to not have audio, as that may cause multiple issues
            archinstall.arguments['audio'] = 'none'
Ejemplo n.º 27
0
import archinstall, getpass, os
from archinstall.lib.general import sys_command
# Select a harddrive and a disk password
archinstall.log(f"Minimal only supports:")
archinstall.log(f" * Being installed to a single disk")
USER = "******"


class AurPackageSet:
    def __init__(self, user):
        self.packages = []
        self.user = user

    def __add__(self, other):
        self.packages.append(other)
        return self

    def __str__(self):
        user = self.user
        output = f"""#!/bin/bash
mkdir -p /home/{user}/.cache/
cd /home/{user}/.cache
    """
        for package in self.packages:
            output += f"""
git clone https://aur.archlinux.org/{package}.git
cd {package}
makepkg -si --noconfirm
cd ..
            """
        return output
Ejemplo n.º 28
0
def log_execution_environment():
	# Log various information about hardware before starting the installation. This might assist in troubleshooting
	archinstall.log(f"Hardware model detected: {archinstall.sys_vendor()} {archinstall.product_name()}; UEFI mode: {archinstall.has_uefi()}", level=logging.DEBUG)
	archinstall.log(f"Processor model detected: {archinstall.cpu_model()}", level=logging.DEBUG)
	archinstall.log(f"Memory statistics: {archinstall.mem_available()} available out of {archinstall.mem_total()} total installed", level=logging.DEBUG)
	archinstall.log(f"Virtualization detected: {archinstall.virtualization()}; is VM: {archinstall.is_vm()}", level=logging.DEBUG)
	archinstall.log(f"Graphics devices detected: {archinstall.graphics_devices().keys()}", level=logging.DEBUG)

	# 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)
Ejemplo n.º 29
0
	# 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)


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)

log_execution_environment()

if not archinstall.check_mirror_reachable():
	log_file = os.path.join(archinstall.storage.get('LOG_PATH', None), archinstall.storage.get('LOG_FILE', None))
	archinstall.log(f"Arch Linux mirrors are not reachable. Please check your internet connection and the log file '{log_file}'.", level=logging.INFO, fg="red")
	exit(1)

if not archinstall.arguments.get('silent'):
	ask_user_questions()

config_output = ConfigurationOutput(archinstall.arguments)
if not archinstall.arguments.get('silent'):
	config_output.show()
config_output.save()

if archinstall.arguments.get('dry_run'):
	exit(0)
if not archinstall.arguments.get('silent'):
	input('Press Enter to continue.')
Ejemplo n.º 30
0
                for kernel in archinstall.storage[
                        'installation_session'].kernels:
                    archinstall.storage[
                        'installation_session'].add_additional_packages(
                            f"{kernel}-headers"
                        )  # Fixes https://github.com/archlinux/archinstall/issues/585
                archinstall.storage[
                    'installation_session'].add_additional_packages(
                        "dkms"
                    )  # I've had kernel regen fail if it wasn't installed before nvidia-dkms
                archinstall.storage[
                    'installation_session'].add_additional_packages(
                        "xorg-server xorg-xinit nvidia-dkms")
            else:
                archinstall.storage[
                    'installation_session'].add_additional_packages(
                        f"xorg-server xorg-xinit {' '.join(archinstall.storage.get('gfx_driver_packages', []))}"
                    )
        else:
            archinstall.storage['installation_session'].add_additional_packages(
                f"xorg-server xorg-xinit {' '.join(archinstall.storage.get('gfx_driver_packages', []))}"
            )
    except Exception as err:
        archinstall.log(
            f"Could not handle nvidia and linuz-zen specific situations during xorg installation: {err}",
            level=logging.WARNING,
            fg="yellow")
        archinstall.storage['installation_session'].add_additional_packages(
            "xorg-server xorg-xinit"
        )  # Prep didn't run, so there's no driver to install