Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib
diff options
context:
space:
mode:
Diffstat (limited to 'archinstall/lib')
-rw-r--r--archinstall/lib/general.py10
-rw-r--r--archinstall/lib/installer.py12
-rw-r--r--archinstall/lib/locale_helpers.py14
-rw-r--r--archinstall/lib/mirrors.py9
-rw-r--r--archinstall/lib/profiles.py3
-rw-r--r--archinstall/lib/services.py2
-rw-r--r--archinstall/lib/user_interaction.py38
7 files changed, 58 insertions, 30 deletions
diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py
index 5b1b3c2a..dc0f018a 100644
--- a/archinstall/lib/general.py
+++ b/archinstall/lib/general.py
@@ -76,7 +76,7 @@ class sys_command():#Thread):
"""
Stolen from archinstall_gui
"""
- def __init__(self, cmd, callback=None, start_callback=None, peak_output=False, *args, **kwargs):
+ def __init__(self, cmd, callback=None, start_callback=None, peak_output=False, environment_vars={}, *args, **kwargs):
kwargs.setdefault("worker_id", gen_uid())
kwargs.setdefault("emulate", False)
kwargs.setdefault("suppress_errors", False)
@@ -102,6 +102,7 @@ class sys_command():#Thread):
self.args = args
self.kwargs = kwargs
self.peak_output = peak_output
+ self.environment_vars = environment_vars
self.kwargs.setdefault("worker", None)
self.callback = callback
@@ -200,7 +201,7 @@ class sys_command():#Thread):
# Replace child process with our main process
if not self.kwargs['emulate']:
try:
- os.execv(self.cmd[0], self.cmd)
+ os.execve(self.cmd[0], self.cmd, {**os.environ, **self.environment_vars})
except FileNotFoundError:
self.status = 'done'
self.log(f"{self.cmd[0]} does not exist.", level=LOG_LEVELS.Debug)
@@ -304,6 +305,11 @@ class sys_command():#Thread):
with open(f'{self.cwd}/trace.log', 'wb') as fh:
fh.write(self.trace_log)
+ try:
+ os.close(child_fd)
+ except:
+ pass
+
def prerequisite_check():
if not os.path.isdir("/sys/firmware/efi"):
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index 2effc7f7..75ef9c4e 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -86,6 +86,7 @@ class Installer():
if not (missing_steps := self.post_install_check()):
self.log('Installation completed without any errors. You may now reboot.', bg='black', fg='green', level=LOG_LEVELS.Info)
self.sync_log_to_install_medium()
+
return True
else:
self.log('Some required steps were not successfully installed/configured before leaving the installer:', bg='black', fg='red', level=LOG_LEVELS.Warning)
@@ -195,6 +196,9 @@ class Installer():
def arch_chroot(self, cmd, *args, **kwargs):
return self.run_command(cmd)
+ def drop_to_shell(self):
+ subprocess.check_call(f"/usr/bin/arch-chroot {self.target}", shell=True)
+
def configure_nic(self, nic, dhcp=True, ip=None, gateway=None, dns=None, *args, **kwargs):
if dhcp:
conf = Networkd(Match={"Name": nic}, Network={"DHCP": "yes"})
@@ -474,10 +478,18 @@ class Installer():
o = b''.join(sys_command(f"/usr/bin/arch-chroot {self.target} sh -c \"echo '{user}:{password}' | chpasswd\""))
pass
+
+ def user_set_shell(self, user, shell):
+ self.log(f'Setting shell for {user} to {shell}', level=LOG_LEVELS.Info)
+
+ o = b''.join(sys_command(f"/usr/bin/arch-chroot {self.target} sh -c \"chsh -s {shell} {user}\""))
+ pass
def set_keyboard_language(self, language):
if len(language.strip()):
with open(f'{self.target}/etc/vconsole.conf', 'w') as vconsole:
vconsole.write(f'KEYMAP={language}\n')
vconsole.write(f'FONT=lat9w-16\n')
+ else:
+ self.log(f'Keyboard language was not changed from default (no language specified).', fg="yellow", level=LOG_LEVELS.Info)
return True
diff --git a/archinstall/lib/locale_helpers.py b/archinstall/lib/locale_helpers.py
index 523a23d5..736bfc47 100644
--- a/archinstall/lib/locale_helpers.py
+++ b/archinstall/lib/locale_helpers.py
@@ -1,29 +1,25 @@
+import subprocess
import os
from .exceptions import *
# from .general import sys_command
-def list_keyboard_languages(layout='qwerty'):
+def list_keyboard_languages():
locale_dir = '/usr/share/kbd/keymaps/'
if not os.path.isdir(locale_dir):
raise RequirementError(f'Directory containing locales does not exist: {locale_dir}')
for root, folders, files in os.walk(locale_dir):
- # Since qwerty is under /i386/ but other layouts are
- # in different spots, we'll need to filter the last foldername
- # of the path to verify against the desired layout.
- if os.path.basename(root) != layout:
- continue
for file in files:
if os.path.splitext(file)[1] == '.gz':
yield file.strip('.gz').strip('.map')
-def search_keyboard_layout(filter, layout='qwerty'):
- for language in list_keyboard_languages(layout):
+def search_keyboard_layout(filter):
+ for language in list_keyboard_languages():
if filter.lower() in language.lower():
yield language
def set_keyboard_language(locale):
- return os.system(f'loadkeys {locale}') == 0
+ return subprocess.call(['loadkeys', locale]) == 0
diff --git a/archinstall/lib/mirrors.py b/archinstall/lib/mirrors.py
index d7d35782..04f47c0d 100644
--- a/archinstall/lib/mirrors.py
+++ b/archinstall/lib/mirrors.py
@@ -74,10 +74,15 @@ def re_rank_mirrors(top=10, *positionals, **kwargs):
def list_mirrors():
url = f"https://archlinux.org/mirrorlist/?protocol=https&ip_version=4&ip_version=6&use_mirror_status=on"
-
- response = urllib.request.urlopen(url)
regions = {}
+ try:
+ response = urllib.request.urlopen(url)
+ except urllib.error.URLError as err:
+ log(f'Could not fetch an active mirror-list: {err}', level=LOG_LEVELS.Warning, fg="yellow")
+ return regions
+
+
region = 'Unknown region'
for line in response.readlines():
if len(line.strip()) == 0:
diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py
index 94d9f6ee..c5f63e72 100644
--- a/archinstall/lib/profiles.py
+++ b/archinstall/lib/profiles.py
@@ -177,7 +177,7 @@ class Profile(Script):
if hasattr(imported, '_prep_function'):
return True
return False
- """
+
def has_post_install(self):
with open(self.path, 'r') as source:
source_data = source.read()
@@ -193,7 +193,6 @@ class Profile(Script):
with self.load_instructions(namespace=f"{self.namespace}.py") as imported:
if hasattr(imported, '_post_install'):
return True
- """
def is_top_level_profile(self):
with open(self.path, 'r') as source:
diff --git a/archinstall/lib/services.py b/archinstall/lib/services.py
index 8fcdd296..bb6f64f2 100644
--- a/archinstall/lib/services.py
+++ b/archinstall/lib/services.py
@@ -7,6 +7,6 @@ def service_state(service_name: str):
if os.path.splitext(service_name)[1] != '.service':
service_name += '.service' # Just to be safe
- state = b''.join(sys_command(f'systemctl show -p SubState --value {service_name}'))
+ state = b''.join(sys_command(f'systemctl show --no-pager -p SubState --value {service_name}', environment_vars={'SYSTEMD_COLORS' : '0'}))
return state.strip().decode('UTF-8')
diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py
index 114c7c6a..822f63be 100644
--- a/archinstall/lib/user_interaction.py
+++ b/archinstall/lib/user_interaction.py
@@ -132,7 +132,9 @@ def ask_for_additional_users(prompt='Any additional users to install (leave blan
return users, super_users
def ask_for_a_timezone():
- timezone = input('Enter a valid timezone (Example: Europe/Stockholm): ').strip()
+ timezone = input('Enter a valid timezone (examples: Europe/Stockholm, US/Eastern) or press enter to use UTC: ').strip()
+ if timezone == '':
+ timezone = 'UTC'
if (pathlib.Path("/usr")/"share"/"zoneinfo"/timezone).exists():
return timezone
else:
@@ -186,7 +188,7 @@ def ask_to_configure_network():
elif nic:
return nic
- return None
+ return {}
def ask_for_disk_layout():
options = {
@@ -323,6 +325,8 @@ def select_language(options, show_only_country_codes=True):
:return: The language/dictionary key of the selected language
:rtype: str
"""
+ DEFAULT_KEYBOARD_LANGUAGE = 'us'
+
if show_only_country_codes:
languages = sorted([language for language in list(options) if len(language) == 2])
else:
@@ -332,9 +336,12 @@ def select_language(options, show_only_country_codes=True):
for index, language in enumerate(languages):
print(f"{index}: {language}")
- print(' -- You can enter ? or help to search for more languages --')
+ print(' -- You can enter ? or help to search for more languages, or skip to use US layout --')
selected_language = input('Select one of the above keyboard languages (by number or full name): ')
- if selected_language.lower() in ('?', 'help'):
+
+ if len(selected_language.strip()) == 0:
+ return DEFAULT_KEYBOARD_LANGUAGE
+ elif selected_language.lower() in ('?', 'help'):
while True:
filter_string = input('Search for layout containing (example: "sv-"): ')
new_options = list(search_keyboard_layout(filter_string))
@@ -347,6 +354,7 @@ def select_language(options, show_only_country_codes=True):
elif selected_language.isdigit() and (pos := int(selected_language)) <= len(languages)-1:
selected_language = languages[pos]
+ return selected_language
# I'm leaving "options" on purpose here.
# Since languages possibly contains a filtered version of
# all possible language layouts, and we might want to write
@@ -354,9 +362,9 @@ def select_language(options, show_only_country_codes=True):
# go through the search step.
elif selected_language in options:
selected_language = options[options.index(selected_language)]
+ return selected_language
else:
- RequirementError("Selected language does not exist.")
- return selected_language
+ raise RequirementError("Selected language does not exist.")
raise RequirementError("Selecting languages require a least one language to be given as an option.")
@@ -380,25 +388,27 @@ def select_mirror_regions(mirrors, show_top_mirrors=True):
selected_mirrors = {}
if len(regions) >= 1:
- print_large_list(regions, margin_bottom=2)
+ print_large_list(regions, margin_bottom=4)
print(' -- You can skip this step by leaving the option blank --')
selected_mirror = input('Select one of the above regions to download packages from (by number or full name): ')
if len(selected_mirror.strip()) == 0:
+ # Returning back empty options which can be both used to
+ # do "if x:" logic as well as do `x.get('mirror', {}).get('sub', None)` chaining
return {}
- elif selected_mirror.isdigit() and (pos := int(selected_mirror)) <= len(regions)-1:
+ elif selected_mirror.isdigit() and int(selected_mirror) <= len(regions)-1:
+ # I'm leaving "mirrors" on purpose here.
+ # Since region possibly contains a known region of
+ # all possible regions, and we might want to write
+ # for instance Sweden (if we know that exists) without having to
+ # go through the search step.
region = regions[int(selected_mirror)]
selected_mirrors[region] = mirrors[region]
- # I'm leaving "mirrors" on purpose here.
- # Since region possibly contains a known region of
- # all possible regions, and we might want to write
- # for instance Sweden (if we know that exists) without having to
- # go through the search step.
elif selected_mirror in mirrors:
selected_mirrors[selected_mirror] = mirrors[selected_mirror]
else:
- RequirementError("Selected region does not exist.")
+ raise RequirementError("Selected region does not exist.")
return selected_mirrors