index : archinstall32 | |
Archlinux32 installer | gitolite user |
summaryrefslogtreecommitdiff |
author | Anton Hvornum <anton.feeds@gmail.com> | 2021-04-07 11:15:42 +0200 |
---|---|---|
committer | Anton Hvornum <anton.feeds@gmail.com> | 2021-04-07 11:15:42 +0200 |
commit | 42470dcc9ae13fca5f46d0f8e1be800744a8a797 (patch) | |
tree | 60696befca281b20e1d631d06f0a6a5b4a0879f1 /archinstall/lib | |
parent | 5ca64b59a605351231f7f9c34e57fadc5f668d9e (diff) | |
parent | 1d60e307e81a99ebd6cbfe26a92e5dfa96a8870a (diff) |
-rw-r--r-- | archinstall/lib/disk.py | 13 | ||||
-rw-r--r-- | archinstall/lib/installer.py | 22 | ||||
-rw-r--r-- | archinstall/lib/luks.py | 2 | ||||
-rw-r--r-- | archinstall/lib/networking.py | 4 | ||||
-rw-r--r-- | archinstall/lib/output.py | 6 | ||||
-rw-r--r-- | archinstall/lib/profiles.py | 14 | ||||
-rw-r--r-- | archinstall/lib/storage.py | 2 | ||||
-rw-r--r-- | archinstall/lib/user_interaction.py | 25 |
diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 4ea9f214..e2f4d76e 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -25,11 +25,12 @@ class BlockDevice(): self.path = path self.info = info + self.keep_partitions = True self.part_cache = OrderedDict() - # TODO: Currently disk encryption is a BIT missleading. + # TODO: Currently disk encryption is a BIT misleading. # It's actually partition-encryption, but for future-proofing this # I'm placing the encryption password on a BlockDevice level. - self.encryption_passwoed = None + self.encryption_password = None def __repr__(self, *args, **kwargs): return f"BlockDevice({self.device})" @@ -285,10 +286,10 @@ class Partition(): handle = luks2(self, None, None) return handle.encrypt(self, *args, **kwargs) - def format(self, filesystem=None, path=None, allow_formatting=None, log_formating=True): + def format(self, filesystem=None, path=None, allow_formatting=None, log_formatting=True): """ Format can be given an overriding path, for instance /dev/null to test - the formating functionality and in essence the support for the given filesystem. + the formatting functionality and in essence the support for the given filesystem. """ if filesystem is None: filesystem = self.filesystem @@ -306,7 +307,7 @@ class Partition(): if not allow_formatting: raise PermissionError(f"{self} is not formatable either because instance is locked ({self.allow_formatting}) or a blocking flag was given ({allow_formatting})") - if log_formating: + if log_formatting: log(f'Formatting {path} -> {filesystem}', level=LOG_LEVELS.Info) if filesystem == 'btrfs': @@ -401,7 +402,7 @@ class Partition(): 2. UnknownFilesystemFormat that indicates that we don't support the given filesystem type """ try: - self.format(self.filesystem, '/dev/null', log_formating=False, allow_formatting=True) + self.format(self.filesystem, '/dev/null', log_formatting=False, allow_formatting=True) except SysCallError: pass # We supported it, but /dev/null is not formatable as expected so the mkfs call exited with an error code except UnknownFilesystemFormat as err: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index a99bc944..c99d0017 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -79,7 +79,7 @@ class Installer(): return self def __exit__(self, *args, **kwargs): - # b''.join(sys_command(f'sync')) # No need to, since the underlaying fs() object will call sync. + # b''.join(sys_command(f'sync')) # No need to, since the underlying fs() object will call sync. # TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager if len(args) >= 2 and args[1]: @@ -91,7 +91,7 @@ class Installer(): # We avoid printing /mnt/<log path> because that might confuse people if they note it down # and then reboot, and a identical log file will be found in the ISO medium anyway. print(f"[!] A log file has been created here: {os.path.join(storage['LOG_PATH'], storage['LOG_FILE'])}") - print(f" Please submit this issue (and file) to https://github.com/Torxed/archinstall/issues") + print(f" Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues") raise args[1] self.genfstab() @@ -104,8 +104,10 @@ class Installer(): self.log('Some required steps were not successfully installed/configured before leaving the installer:', bg='black', fg='red', level=LOG_LEVELS.Warning) for step in missing_steps: self.log(f' - {step}', bg='black', fg='red', level=LOG_LEVELS.Warning) - self.log(f"Detailed error logs can be found at: {log_path}", level=LOG_LEVELS.Warning) - self.log(f"Submit this zip file as an issue to https://github.com/Torxed/archinstall/issues", level=LOG_LEVELS.Warning) + + self.log(f"Detailed error logs can be found at: {storage['LOG_PATH']}", level=LOG_LEVELS.Warning) + self.log(f"Submit this zip file as an issue to https://github.com/archlinux/archinstall/issues", level=LOG_LEVELS.Warning) + self.sync_log_to_install_medium() return False @@ -151,11 +153,11 @@ class Installer(): self.log(f"Updating {self.mountpoint}/etc/fstab", level=LOG_LEVELS.Info) fstab = sys_command(f'/usr/bin/genfstab {flags} {self.mountpoint}').trace_log - with open(f"{self.mountpoint}/etc/fstab", 'ab') as fstab_fh: + with open(f"{self.mountpoint}/etc/fstab", 'ab',newline='\n') as fstab_fh: fstab_fh.write(fstab) if not os.path.isfile(f'{self.mountpoint}/etc/fstab'): - raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n{o}') + raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n{b"".join(fstab)}') return True @@ -274,7 +276,7 @@ class Installer(): return True def minimal_installation(self): - ## Add nessecary packages if encrypting the drive + ## Add necessary packages if encrypting the drive ## (encrypted partitions default to btrfs for now, so we need btrfs-progs) ## TODO: Perhaps this should be living in the function which dictates ## the partitioning. Leaving here for now. @@ -312,14 +314,14 @@ class Installer(): mkinit.write('MODULES=(btrfs)\n') mkinit.write('BINARIES=(/usr/bin/btrfs)\n') mkinit.write('FILES=()\n') - mkinit.write('HOOKS=(base udev autodetect modconf block encrypt filesystems keymap keyboard fsck)\n') + mkinit.write('HOOKS=(base udev autodetect keyboard keymap modconf block encrypt filesystems fsck)\n') sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux') elif self.partition.encrypted: with open(f'{self.mountpoint}/etc/mkinitcpio.conf', 'w') as mkinit: mkinit.write('MODULES=()\n') mkinit.write('BINARIES=()\n') mkinit.write('FILES=()\n') - mkinit.write('HOOKS=(base udev autodetect modconf block encrypt filesystems keymap keyboard fsck)\n') + mkinit.write('HOOKS=(base udev autodetect keyboard keymap modconf block encrypt filesystems fsck)\n') sys_command(f'/usr/bin/arch-chroot {self.mountpoint} mkinitcpio -p linux') self.helper_flags['base'] = True @@ -419,7 +421,7 @@ class Installer(): # The tricky thing with doing the import archinstall.session instead is that # profiles might be run from a different chroot, and there's no way we can # guarantee file-path safety when accessing the installer object that way. - # Doing the __builtins__ replacement, ensures that the global vriable "installation" + # Doing the __builtins__ replacement, ensures that the global variable "installation" # is always kept up to date. It's considered a nasty hack - but it's a safe way # of ensuring 100% accuracy of archinstall session variables. __builtins__['installation'] = self diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 62067ec1..a1d42196 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -43,8 +43,6 @@ class luks2(): return True def encrypt(self, partition, password=None, key_size=512, hash_type='sha512', iter_time=10000, key_file=None): - # TODO: We should be able to integrate this into the main log some how. - # Perhaps post-mortem? if not self.partition.allow_formatting: raise DiskError(f'Could not encrypt volume {self.partition} due to it having a formatting lock.') diff --git a/archinstall/lib/networking.py b/archinstall/lib/networking.py index 882bcff3..2dc8be9b 100644 --- a/archinstall/lib/networking.py +++ b/archinstall/lib/networking.py @@ -56,7 +56,7 @@ def wirelessScan(interface): storage['_WIFI'][interface]['scanning'] = True -# TOOD: Full WiFi experience might get evolved in the future, pausing for now 2021-01-25 +# TODO: Full WiFi experience might get evolved in the future, pausing for now 2021-01-25 def getWirelessNetworks(interface): # TODO: Make this oneliner pritter to check if the interface is scanning or not. if not '_WIFI' in storage or interface not in storage['_WIFI'] or storage['_WIFI'][interface].get('scanning', False) is False: @@ -65,4 +65,4 @@ def getWirelessNetworks(interface): time.sleep(5) for line in sys_command(f"iwctl station {interface} get-networks"): - print(line)
\ No newline at end of file + print(line) diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py index 537fb695..6b184b4b 100644 --- a/archinstall/lib/output.py +++ b/archinstall/lib/output.py @@ -6,7 +6,7 @@ from pathlib import Path from .storage import storage # TODO: use logging's built in levels instead. -# Altough logging is threaded and I wish to avoid that. +# Although logging is threaded and I wish to avoid that. # It's more Pythonistic or w/e you want to call it. class LOG_LEVELS: Critical = 0b001 @@ -88,7 +88,7 @@ def log(*args, **kwargs): # Attempt to colorize the output if supported # Insert default colors and override with **kwargs if supports_color(): - kwargs = {'bg' : 'black', 'fg': 'white', **kwargs} + kwargs = {'fg': 'white', **kwargs} string = stylize_output(string, **kwargs) # If a logfile is defined in storage, @@ -130,4 +130,4 @@ def log(*args, **kwargs): # We use sys.stdout.write()+flush() instead of print() to try and # fix issue #94 sys.stdout.write(f"{string}\n") - sys.stdout.flush()
\ No newline at end of file + sys.stdout.flush() diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 70c21a67..39411553 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -112,11 +112,11 @@ class Script(): if f"{self.profile}" in self.examples: return self.localize_path(self.examples[self.profile]['path']) - # TODO: Redundant, the below block shouldnt be needed as profiles are stripped of their .py, but just in case for now: + # TODO: Redundant, the below block shouldn't be needed as profiles are stripped of their .py, but just in case for now: elif f"{self.profile}.py" in self.examples: return self.localize_path(self.examples[f"{self.profile}.py"]['path']) - # Path was not found in any known examples, check if it's an abolute path + # Path was not found in any known examples, check if it's an absolute path if os.path.isfile(self.profile): return self.profile @@ -156,7 +156,7 @@ class Profile(Script): def install(self): # Before installing, revert any temporary changes to the namespace. - # This ensures that the namespace during installation is the original initation namespace. + # This ensures that the namespace during installation is the original initiation namespace. # (For instance awesome instead of aweosme.py or app-awesome.py) self.namespace = self.original_namespace return self.execute() @@ -231,11 +231,11 @@ class Application(Profile): if f"{self.profile}" in self.examples: return self.localize_path(self.examples[self.profile]['path']) - # TODO: Redundant, the below block shouldnt be needed as profiles are stripped of their .py, but just in case for now: + # TODO: Redundant, the below block shouldn't be needed as profiles are stripped of their .py, but just in case for now: elif f"{self.profile}.py" in self.examples: return self.localize_path(self.examples[f"{self.profile}.py"]['path']) - # Path was not found in any known examples, check if it's an abolute path + # Path was not found in any known examples, check if it's an absolute path if os.path.isfile(self.profile): return os.path.basename(self.profile) @@ -247,7 +247,7 @@ class Application(Profile): def install(self): # Before installing, revert any temporary changes to the namespace. - # This ensures that the namespace during installation is the original initation namespace. + # This ensures that the namespace during installation is the original initiation namespace. # (For instance awesome instead of aweosme.py or app-awesome.py) self.namespace = self.original_namespace - return self.execute()
\ No newline at end of file + return self.execute() diff --git a/archinstall/lib/storage.py b/archinstall/lib/storage.py index 9bda017d..43d088bb 100644 --- a/archinstall/lib/storage.py +++ b/archinstall/lib/storage.py @@ -14,7 +14,7 @@ storage = { os.path.join(os.path.dirname(os.path.abspath(__file__)), 'profiles'), #os.path.abspath(f'{os.path.dirname(__file__)}/../examples') ], - 'UPSTREAM_URL' : 'https://raw.githubusercontent.com/Torxed/archinstall/master/profiles', + 'UPSTREAM_URL' : 'https://raw.githubusercontent.com/archlinux/archinstall/master/profiles', 'PROFILE_DB' : None, # Used in cases when listing profiles is desired, not mandatory for direct profile grabing. 'LOG_PATH' : '/var/log/archinstall', 'LOG_FILE' : 'install.log', diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py index 58f88bd2..63630515 100644 --- a/archinstall/lib/user_interaction.py +++ b/archinstall/lib/user_interaction.py @@ -1,4 +1,4 @@ -import getpass, pathlib, os, shutil +import getpass, pathlib, os, shutil, re from .exceptions import * from .profiles import Profile from .locale_helpers import search_keyboard_layout @@ -18,11 +18,21 @@ def get_terminal_width(): def get_longest_option(options): return max([len(x) for x in options]) +def check_for_correct_username(username): + if re.match(r'^[a-z_][a-z0-9_-]*\$?$', username) and len(username) <= 32: + return True + log( + "The username you entered is invalid. Try again", + level=LOG_LEVELS.Warning, + fg='red' + ) + return False + def get_password(prompt="Enter a password: "): while (passwd := getpass.getpass(prompt)): passwd_verification = getpass.getpass(prompt='And one more time for verification: ') if passwd != passwd_verification: - log(' * Passwords did not match * ', bg='black', fg='red') + log(' * Passwords did not match * ', fg='red') continue if len(passwd.strip()) <= 0: @@ -50,14 +60,16 @@ def print_large_list(options, padding=5, margin_bottom=0, separator=': '): def ask_for_superuser_account(prompt='Create a required super-user with sudo privileges: ', forced=False): while 1: new_user = input(prompt).strip(' ') - + if not new_user and forced: # TODO: make this text more generic? # It's only used to create the first sudo user when root is disabled in guided.py - log(' * Since root is disabled, you need to create a least one (super) user!', bg='black', fg='red') + log(' * Since root is disabled, you need to create a least one (super) user!', fg='red') continue elif not new_user and not forced: raise UserError("No superuser was created.") + elif not check_for_correct_username(new_user): + continue password = get_password(prompt=f'Password for user {new_user}: ') return {new_user: {"!password" : password}} @@ -70,6 +82,8 @@ def ask_for_additional_users(prompt='Any additional users to install (leave blan new_user = input(prompt).strip(' ') if not new_user: break + if not check_for_correct_username(new_user): + continue password = get_password(prompt=f'Password for user {new_user}: ') if input("Should this user be a sudo (super) user (y/N): ").strip(' ').lower() in ('y', 'yes'): @@ -110,7 +124,6 @@ def ask_to_configure_network(): log( "You need to enter a valid IP in IP-config mode.", level=LOG_LEVELS.Warning, - bg='black', fg='red' ) @@ -153,7 +166,7 @@ def ask_for_main_filesystem_format(): def generic_select(options, input_text="Select one of the above by index or absolute value: ", sort=True): """ A generic select function that does not output anything - other than the options and their indexs. As an example: + other than the options and their indexes. As an example: generic_select(["first", "second", "third option"]) 1: first |