From 47fdf30fe1cbf74f2e45dcf58b317f7a1168d542 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 15 Nov 2019 23:57:57 +0000 Subject: Starting to move individual steps into functions instead, so that they can be called externally as a library instead. Useful for graphical frontends and what not --- archinstall.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/archinstall.py b/archinstall.py index 10266545..90f4d056 100644 --- a/archinstall.py +++ b/archinstall.py @@ -11,10 +11,13 @@ from time import sleep, time from random import choice from string import ascii_uppercase, ascii_lowercase, digits +if not os.path.isdir('/sys/firmware/efi'): + print('[E] This script only supports UEFI-booted machines.') + exit(1) + ## == Profiles Path can be set via --profiles-path=/path ## This just sets the default path if the parameter is omitted. profiles_path = 'https://raw.githubusercontent.com/Torxed/archinstall/master/deployments' - try: import psutil except: @@ -495,14 +498,7 @@ def merge_dicts(d1, d2, before=True, overwrite=False): def random_string(l): return ''.join(choice(ascii_uppercase + ascii_lowercase + digits) for i in range(l)) -if __name__ == '__main__': - update_git() # Breaks and restarts the script if an update was found. - update_drive_list() - if not os.path.isdir('/sys/firmware/efi'): - print('[E] This script only supports UEFI-booted machines.') - exit(1) - - ## Setup some defaults (in case no command-line parameters or netdeploy-params were given) +def setup_args_defaults(args): if not 'size' in args: args['size'] = '100%' if not 'start' in args: args['start'] = '513MiB' if not 'pwfile' in args: args['pwfile'] = '/tmp/diskpw' @@ -542,9 +538,9 @@ if __name__ == '__main__': exit(1) args['drive'] = drive + return args - ## == If we got networking, - # Try fetching instructions for this box and execute them. +def load_instruction_set(): instructions = {} if get_default_gateway_linux(): locmac = get_local_MACs() @@ -572,6 +568,20 @@ if __name__ == '__main__': else: print('[N] No gateway - No net deploy') + return instructions + +if __name__ == '__main__': + update_git() # Breaks and restarts the script if an update was found. + update_drive_list() + + ## Setup some defaults + # (in case no command-line parameters or netdeploy-params were given) + args = setup_args_defaults(args) + + ## == If we got networking, + # Try fetching instructions for this box and execute them. + instructions = load_instruction_set() + if args['profile'] and not args['default']: instructions = get_instructions(args['profile']) if len(instructions) <= 0: @@ -642,8 +652,6 @@ if __name__ == '__main__': # with open(args['pwfile'], 'r') as pw: # PIN = pw.read().strip() - - print() print('[!] Disk PASSWORD is: {}'.format(args['password'])) print() -- cgit v1.2.3-70-g09d2 From 42f6550879fc9524af4181be5f0bf150feeb0ccd Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 17 Nov 2019 12:30:10 +0000 Subject: Added new ways to get the disk size, since os.statvfs() won't work on unmounted drives. Also moving more stuff into functions. --- archinstall.py | 90 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/archinstall.py b/archinstall.py index 90f4d056..c7db4e69 100644 --- a/archinstall.py +++ b/archinstall.py @@ -30,7 +30,8 @@ except: class disk(): def __init__(self, size, free, percent): - self.size = size + self.total = size + self.used = 0 self.free = free self.percent = percent @@ -307,7 +308,7 @@ def get_drive_from_part_uuid(partuuid): if len(harddrives) <= 0: raise ValueError("No hard drives to iterate in order to find: {}".format(uuid)) for drive in harddrives: - for partition in grab_partitions(f'/dev/{drive}'): + for partition in get_partitions(f'/dev/{drive}'): o = simple_command(f'blkid -s PARTUUID -o value /dev/{drive}') if len(o) and o == partuuid: return drive @@ -372,7 +373,7 @@ def device_state(name): return return True -def grab_partitions(dev): +def get_partitions(dev): drive_name = os.path.basename(dev) parts = oDict() #o = b''.join(sys_command('/usr/bin/lsblk -o name -J -b {dev}'.format(dev=dev)).exec()) @@ -398,11 +399,74 @@ def grab_partitions(dev): return parts +def get_disk_model(drive): + with open(f'/sys/block/{os.path.basename(drive)}/device/model', 'rb') as fh: + return fh.read().decode('UTF-8').strip() + +def get_disk_size(drive): + dev_short_name = os.path.basename(drive) + with open(f'/sys/block/{dev_short_name}/device/block/{dev_short_name}/size', 'rb') as fh: + return ''.join(human_readable_size(fh.read().decode('UTF-8').strip())) + +def disk_info(drive): + info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}').exec()).decode('UTF_8'))['blockdevices'][0] + fileformats = [] + labels = [] + for child in info['children']: + if child['fstype'] != None: + fileformats.append(child['fstype']) + if child['label'] != None: + labels.append(child['label']) + info['fileformats'] = fileformats + info['labels'] = labels + info['model'] = get_disk_model(drive) + + return info + def update_drive_list(): + # https://github.com/karelzak/util-linux/blob/f920f73d83f8fd52e7a14ec0385f61fab448b491/disk-utils/fdisk-list.c#L52 for path in glob('/sys/block/*/device'): name = re.sub('.*/(.*?)/device', '\g<1>', path) if device_state(name): - harddrives['/dev/{}'.format(name)] = psutil.disk_usage('/dev/{}'.format(name)) + harddrives[f'/dev/{name}'] = disk_info(f'/dev/{name}') + +def human_readable_size(bits, sizes=[{8 : 'b'}, {1024 : 'kb'}, {1024 : 'mb'}, {1024 : 'gb'}, {1024 : 'tb'}, {1024 : 'zb?'}]): + # Not needed if using lsblk. + end_human = None + for pair in sizes: + size, human = list(pair.items())[0] + + if bits / size > 1: + bits = bits/size + end_human = human + else: + break + return bits, end_human + +def human_disk_info(drive): + return { + 'size' : harddrives[drive]['size'], + 'fileformat' : harddrives[drive]['fileformats'], + 'labels' : harddrives[drive]['labels'] + } + +def close_disks(): + o = simple_command('/usr/bin/umount -R /mnt') + o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') + +def format_disk(drive, start='512MiB', end='100%'): + print(f'[N] Setting up {drive}.') + # dd if=/dev/random of=args['drive'] bs=4096 status=progress + # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mklabel gpt').exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}').exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"').exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 esp on').exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 boot on').exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {size}').exec()) + # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. + # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. + # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P def multisplit(s, splitters): s = [s,] @@ -661,22 +725,10 @@ if __name__ == '__main__': print(f'Formatting {args["drive"]} in {i}...') sleep(1) - o = simple_command('/usr/bin/umount -R /mnt') - o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') - print('[N] Setting up {drive}.'.format(**args)) - # dd if=/dev/random of=args['drive'] bs=4096 status=progress - # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda - o = b''.join(sys_command('/usr/bin/parted -s {drive} mklabel gpt'.format(**args)).exec()) - o = b''.join(sys_command('/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}'.format(**args)).exec()) - o = b''.join(sys_command('/usr/bin/parted -s {drive} name 1 "EFI"'.format(**args)).exec()) - o = b''.join(sys_command('/usr/bin/parted -s {drive} set 1 esp on'.format(**args)).exec()) - o = b''.join(sys_command('/usr/bin/parted -s {drive} set 1 boot on'.format(**args)).exec()) - o = b''.join(sys_command('/usr/bin/parted -s {drive} mkpart primary {start} {size}'.format(**args)).exec()) - # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. - # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. - # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P + close_disks() + format_disk(args['drive'], start=args['start'], end=args['size']) - args['paritions'] = grab_partitions(args['drive']) + args['paritions'] = get_partitions(args['drive']) print(f'Partitions: (Boot: {list(args["paritions"].keys())[0]})') if len(args['paritions']) <= 0: -- cgit v1.2.3-70-g09d2 From 7e80c916e8f40ce019fa60edaa3cb818492a2494 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 17 Nov 2019 13:15:40 +0000 Subject: Improved sys_command(). Also added a commandhistory-log and emulation mode --- archinstall.py | 302 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 187 insertions(+), 115 deletions(-) diff --git a/archinstall.py b/archinstall.py index c7db4e69..309dd8a4 100644 --- a/archinstall.py +++ b/archinstall.py @@ -10,14 +10,75 @@ from subprocess import Popen, STDOUT, PIPE from time import sleep, time from random import choice from string import ascii_uppercase, ascii_lowercase, digits +from hashlib import sha512 if not os.path.isdir('/sys/firmware/efi'): print('[E] This script only supports UEFI-booted machines.') exit(1) + +if os.path.isfile('./SAFETY_LOCK'): + SAFETY_LOCK = True +else: + SAFETY_LOCK = False + +profiles_path = 'https://raw.githubusercontent.com/Torxed/archinstall/master/deployments' +rootdir_pattern = re.compile('^.*?/devices') +harddrives = oDict() +commandlog = oDict() +args = {} +positionals = [] +for arg in sys.argv[1:]: + if '--' == arg[:2]: + if '=' in arg: + key, val = [x.strip() for x in arg[2:].split('=')] + else: + key, val = arg[2:], True + args[key] = val + else: + positionals.append(arg) + + +import logging +from systemd.journal import JournalHandler + +# Custom adapter to pre-pend the 'origin' key. +# TODO: Should probably use filters: https://docs.python.org/3/howto/logging-cookbook.html#using-filters-to-impart-contextual-information +class CustomAdapter(logging.LoggerAdapter): + def process(self, msg, kwargs): + return '[{}] {}'.format(self.extra['origin'], msg), kwargs + +logger = logging.getLogger() # __name__ +journald_handler = JournalHandler() +journald_handler.setFormatter(logging.Formatter('[{levelname}] {message}', style='{')) +logger.addHandler(journald_handler) +logger.setLevel(logging.DEBUG) + +class LOG_LEVELS: + CRITICAL = 1 + ERROR = 2 + WARNING = 3 + INFO = 4 + DEBUG = 5 + +def log(*msg, origin='UNKNOWN', level=5, **kwargs): + if level <= LOG_LEVEL: + msg = [item.decode('UTF-8', errors='backslashreplace') if type(item) == bytes else item for item in msg] + msg = [str(item) if type(item) != str else item for item in msg] + log_adapter = CustomAdapter(logger, {'origin': origin}) + if level <= 1: + log_adapter.critical(' '.join(msg)) + elif level <= 2: + log_adapter.error(' '.join(msg)) + elif level <= 3: + log_adapter.warning(' '.join(msg)) + elif level <= 4: + log_adapter.info(' '.join(msg)) + else: + log_adapter.debug(' '.join(msg)) + ## == Profiles Path can be set via --profiles-path=/path ## This just sets the default path if the parameter is omitted. -profiles_path = 'https://raw.githubusercontent.com/Torxed/archinstall/master/deployments' try: import psutil except: @@ -77,6 +138,7 @@ except: data[interface] = iostat(interface, *line.strip().decode('UTF-8').split(' ',1)) return data + ## FIXME: dependency checks (fdisk, lsblk etc) def sig_handler(signal, frame): print('\nAborting further installation steps!') @@ -86,21 +148,8 @@ def sig_handler(signal, frame): exit(0) signal.signal(signal.SIGINT, sig_handler) - -rootdir_pattern = re.compile('^.*?/devices') -harddrives = oDict() - -args = {} -positionals = [] -for arg in sys.argv[1:]: - if '--' == arg[:2]: - if '=' in arg: - key, val = [x.strip() for x in arg[2:].split('=')] - else: - key, val = arg[2:], True - args[key] = val - else: - positionals.append(arg) +def gen_uid(entropy_length=256): + return sha512(os.urandom(entropy_length)).hexdigest() def get_default_gateway_linux(): """Read the default gateway directly from /proc.""" @@ -135,68 +184,108 @@ def pid_exists(pid): else: return True -class sys_command(): - def __init__(self, cmd, opts={}): +class sys_command(Thread): + def __init__(self, cmd, callback=None, start_callback=None, *args, **kwargs): + if not 'worker_id' in kwargs: kwargs['worker_id'] = gen_uid() + if not 'emulate' in kwargs: kwargs['emulate'] = SAFETY_LOCK + Thread.__init__(self) + if self.kwargs['emulate']: + print('Starting command in emulation mode.') self.cmd = shlex.split(cmd) - self.opts = opts - self.pid = -1 - - def __enter__(self, *args, **kwargs): - ## Prep for context management (still block calls) - return self.exec() - - def __leave__(self, *args, **kwargs): - if 'debug' in self.opts and self.opts['debug']: - print('[N] Leaving subsystem routine.') - os.waitpid(self.pid, 0) - if 'debug' in self.opts and self.opts['debug']: - print('[N] (Bye bye!)') - - def exec(self): + self.args = args + self.kwargs = kwargs + self.callback = callback + self.pid = None + self.exit_code = None + self.started = time.time() + self.ended = None + self.worker_id = kwargs['worker_id'] + self.trace_log = b'' + self.status = 'starting' + + user_catalogue = os.path.expanduser('~') + self.cwd = f"{user_catalogue}/archinstall/cache/workers/{kwargs['worker_id']}/" + self.exec_dir = f'{self.cwd}/{basename(self.cmd[0])}_workingdir' + if not self.cmd[0][0] == '/': - print('[N] Command is not executed with absolute path, trying to find: {}'.format(self.cmd[0])) + log('Worker command is not executed with absolute path, trying to find: {}'.format(self.cmd[0]), origin='spawn', level=5) o = b''.join(sys_command('/usr/bin/which {}'.format(self.cmd[0])).exec()) + log('This is the binary {} for {}'.format(o.decode('UTF-8'), self.cmd[0]), origin='spawn', level=5) self.cmd[0] = o.decode('UTF-8') - print('[N] This is what I\'m going with: {}'.format(self.cmd[0])) - # PID = 0 for child, and the PID of the child for the parent - self.pid, child_fd = pty.fork() + if not isdir(self.exec_dir): + os.makedirs(self.exec_dir) + + commandlog.append(cmd + ' #emulated') + if start_callback: start_callback(self, *args, **kwargs) + self.start() + + def __repr__(self, *args, **kwargs): + return self.trace_log.decode('UTF-8') + + def dump(self): + return { + 'status' : self.status, + 'worker_id' : self.worker_id, + 'worker_result' : self.trace_log.decode('UTF-8'), + 'started' : self.started, + 'ended' : self.ended, + 'started_pprint' : '{}-{}-{} {}:{}:{}'.format(*time.localtime(self.started)), + 'ended_pprint' : '{}-{}-{} {}:{}:{}'.format(*time.localtime(self.ended)) if self.ended else None, + 'exit_code' : self.exit_code + } + + def run(self): + main = None + for t in tenum(): + if t.name == 'MainThread': + main = t + break + + if not main: + print('Main thread not existing') + return + + self.status = 'running' + old_dir = os.getcwd() + os.chdir(self.exec_dir) + self.pid, child_fd = pty.fork() if not self.pid: # Child process # Replace child process with our main process - os.execv(self.cmd[0], self.cmd) + if not self.kwargs['emulate']: + os.execv(self.cmd[0], self.cmd) + os.chdir(old_dir) poller = epoll() poller.register(child_fd, EPOLLIN | EPOLLHUP) alive = True - trace_log = b'' last_trigger_pos = 0 - while alive: + while alive and main and main.isAlive() and not self.kwargs['emulate']: for fileno, event in poller.poll(0.1): try: output = os.read(child_fd, 8192).strip() - trace_log += output + self.trace_log += output except OSError: alive = False break - if 'debug' in self.opts and self.opts['debug']: - if len(output): - print(output) + if 'debug' in self.kwargs and self.kwargs['debug'] and len(output): + log(self.cmd[0],'gave:', output.decode('UTF-8'), origin='spawn', level=4) lower = output.lower() broke = False - if 'triggers' in self.opts: - for trigger in list(self.opts['triggers']): - if trigger.lower() in trace_log[last_trigger_pos:].lower(): - trigger_pos_in_log = trace_log[last_trigger_pos:].lower().find(trigger.lower()) + len(trigger) + if 'events' in self.kwargs: + for trigger in list(self.kwargs['events']): + if trigger.lower() in self.trace_log[last_trigger_pos:].lower(): + trigger_pos = self.trace_log[last_trigger_pos:].lower().find(trigger.lower()) - if 'debug' in self.opts and self.opts['debug']: - print('[N] Writing to subsystem: {}'.format(self.opts['triggers'][trigger].decode('UTF-8'))) + if 'debug' in self.kwargs and self.kwargs['debug']: + log(f"Writing to subprocess {self.cmd[0]}: {self.kwargs['events'][trigger].decode('UTF-8')}", origin='spawn', level=5) - last_trigger_pos = trigger_pos_in_log #len(trace_log) - os.write(child_fd, self.opts['triggers'][trigger]) - del(self.opts['triggers'][trigger]) + last_trigger_pos = trigger_pos + os.write(child_fd, self.kwargs['events'][trigger]) + del(self.kwargs['events'][trigger]) broke = True break @@ -204,72 +293,55 @@ class sys_command(): continue ## Adding a exit trigger: - if len(self.opts['triggers']) == 0: - if 'debug' in self.opts and self.opts['debug']: - print('[N] Waiting for last command to finish...') - if bytes(f'[root@{args["hostname"]} ~]#'.lower(), 'UTF-8') in trace_log[0-len(f'[root@{args["hostname"]} ~]#')-5:].lower(): - if 'debug' in self.opts and self.opts['debug']: - print('[N] Last command finished, exiting subsystem.') + if len(self.kwargs['events']) == 0: + if 'debug' in self.kwargs and self.kwargs['debug']: + log(f"Waiting for last command {self.cmd[0]} to finish.", origin='spawn', level=4) + + if bytes(f']$'.lower(), 'UTF-8') in self.trace_log[0-len(f']$')-5:].lower(): + if 'debug' in self.kwargs and self.kwargs['debug']: + log(f"{self.cmd[0]} has finished.", origin='spawn', level=4) alive = False break - yield output - # Gracefully wait for the last output to be given to us from the above command. - # Or break on OSError (process has died) - last = time() - while time()-last < 5: - for fileno, event in poller.poll(0.1): - try: - output = os.read(child_fd, 8192).strip() - trace_log += output - except OSError: - last = time() - 60 - break - - if 'debug' in self.opts and self.opts['debug']: - if len(output): - print(output) - - last = time() + self.status = 'done' - if 'debug' in self.opts and self.opts['debug']: - print('[N] Exited subsystem, instructing it to shutdown.') - # Since we're in a subsystem, we gotta bail out! - # Bail bail bail! - os.write(child_fd, b'shutdown now\n') + if 'debug' in self.kwargs and self.kwargs['debug']: + log(f"{self.cmd[0]} waiting for exit code.", origin='spawn', level=5) - # We need to flush the output of shutdown now, otherwise the - # Popen() handle will hang and we'll never exit out of os.waitpid() later on. - alive = True - while alive: - for fileno, event in poller.poll(0.1): + if not self.kwargs['emulate']: + try: + self.exit_code = os.waitpid(self.pid, 0)[1] + except ChildProcessError: try: - output = os.read(child_fd, 8192).strip() - trace_log += output - except OSError: - alive = False - break + self.exit_code = os.waitpid(child_fd, 0)[1] + except ChildProcessError: + self.exit_code = 1 + else: + self.exit_code = 0 - if 'debug' in self.opts and self.opts['debug']: - if len(output): - print(output) + if self.exit_code != 0: + log(f"{self.cmd[0]} did not exit gracefully, exit code {self.exit_code}.", origin='spawn', level=3) + log(self.trace_log.decode('UTF-8'), origin='spawn', level=3) + else: + log(f"{self.cmd[0]} exit nicely.", origin='spawn', level=5) - if b'Container temporary has been shutdown.' in trace_log[0-len('Container temporary has been shutdown.')-5:]: - alive = False - break + self.ended = time.time() + with open(f'{self.cwd}/trace.log', 'wb') as fh: + fh.write(self.trace_log) - if 'debug' in self.opts and self.opts['debug']: - print('[N] Waiting for exit code.') - exit_code = os.waitpid(self.pid, 0)[1] + worker_history[self.worker_id] = self.dump() - if exit_code != 0: - print(trace_log.decode('UTF-8')) - print('[E] Command "{}" on line ~150 exited with status code:'.format(self.cmd[0]), exit_code) - print('[?] Command executed: {}'.format(self.cmd)) - exit(1) + if 'dependency' in self.kwargs and self.exit_code == 0: + ## If this had a dependency waiting, + ## Start it since there's no hook for this yet, the worker has to spawn it's waiting workers. + module = self.kwargs['dependency']['module'] + print(self.cmd[0],'fullfills a dependency:', module) + dependency_id = self.kwargs['dependency']['id'] + dependencies[module][dependency_id]['fullfilled'] = True + dependencies[module][dependency_id]['spawn'](*dependencies[module][dependency_id]['args'], **dependencies[module][dependency_id]['kwargs'], start_callback=_worker_started_notification) - if 'debug' in self.opts and self.opts['debug']: - print('[N] Subsystem routine complete.') + if self.callback: + self.callback(self, *self.args, **self.kwargs) def simple_command(cmd, opts=None, *args, **kwargs): if not opts: opts = {} @@ -454,16 +526,16 @@ def close_disks(): o = simple_command('/usr/bin/umount -R /mnt') o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') -def format_disk(drive, start='512MiB', end='100%'): +def format_disk(drive, start='512MiB', end='100%', emulate=False): print(f'[N] Setting up {drive}.') # dd if=/dev/random of=args['drive'] bs=4096 status=progress # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mklabel gpt').exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}').exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"').exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 esp on').exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 boot on').exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {size}').exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate).exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}', emulate=emulate).exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate).exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate).exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate).exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {size}', emulate=emulate).exec()) # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P -- cgit v1.2.3-70-g09d2 From d299b188faa4626b55e96f10e520f05df7ac176a Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 17 Nov 2019 13:16:23 +0000 Subject: Adde a gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..45939095 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/**__pycache__ +SAFETY_LOCK -- cgit v1.2.3-70-g09d2 From 5833905e1b1a3081df31be16453e5e47c43fc684 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 17 Nov 2019 13:30:29 +0000 Subject: Cleaning up some more --- archinstall.py | 84 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/archinstall.py b/archinstall.py index 309dd8a4..1d0bba3d 100644 --- a/archinstall.py +++ b/archinstall.py @@ -25,6 +25,7 @@ profiles_path = 'https://raw.githubusercontent.com/Torxed/archinstall/master/dep rootdir_pattern = re.compile('^.*?/devices') harddrives = oDict() commandlog = oDict() +instructions = args = {} positionals = [] for arg in sys.argv[1:]: @@ -495,6 +496,42 @@ def disk_info(drive): return info +def cleanup_args(): + for key in args: + if args[key] == '': args[key] = input(f'Enter a value for {key}: ') + elif args[key] == '': args[key] = random_string(32) + elif args[key] == '': + args[key] = gen_yubikey_password() + if not args[key]: + print('[E] Failed to setup a yubikey password, is it plugged in?') + exit(1) + +def merge_in_includes(instructions): + if 'args' in instructions: + ## == Recursively fetch instructions if "include" is found under {args: ...} + while 'include' in instructions['args']: + includes = instructions['args']['include'] + print('[!] Importing net-deploy target: {}'.format(includes)) + del(instructions['args']['include']) + if type(includes) in (dict, list): + for include in includes: + instructions = merge_dicts(instructions, get_instructions(include), before=True) + else: + instructions = merge_dicts(instructions, get_instructions(includes), before=True) + + ## Update arguments if we found any + for key, val in instructions['args'].items(): + args[key] = val + + if 'args' in instructions: + ## TODO: Reuseable code, there's to many get_instructions, merge_dictgs and args updating going on. + ## Update arguments if we found any + for key, val in instructions['args'].items(): + args[key] = val + + return instructions + + def update_drive_list(): # https://github.com/karelzak/util-linux/blob/f920f73d83f8fd52e7a14ec0385f61fab448b491/disk-utils/fdisk-list.c#L52 for path in glob('/sys/block/*/device'): @@ -589,7 +626,7 @@ def get_application_instructions(target): return instructions def get_instructions(target): - instructions = {} + instructions = oDict() try: instructions = grab_url_data('{}/{}.json'.format(args['profiles-path'], target)).decode('UTF-8') print('[N] Found net-deploy instructions called: {}'.format(target)) @@ -676,8 +713,8 @@ def setup_args_defaults(args): args['drive'] = drive return args -def load_instruction_set(): - instructions = {} +def load_automatic_instructions(): + instructions = oDict() if get_default_gateway_linux(): locmac = get_local_MACs() if not len(locmac): @@ -716,7 +753,7 @@ if __name__ == '__main__': ## == If we got networking, # Try fetching instructions for this box and execute them. - instructions = load_instruction_set() + instructions = load_automatic_instructions() if args['profile'] and not args['default']: instructions = get_instructions(args['profile']) @@ -736,42 +773,9 @@ if __name__ == '__main__': print(' (this is because --default is not instructed and no --profile given)') first = False - - if 'args' in instructions: - ## == Recursively fetch instructions if "include" is found under {args: ...} - while 'include' in instructions['args']: - includes = instructions['args']['include'] - print('[!] Importing net-deploy target: {}'.format(includes)) - del(instructions['args']['include']) - if type(includes) in (dict, list): - for include in includes: - instructions = merge_dicts(instructions, get_instructions(include), before=True) - else: - instructions = merge_dicts(instructions, get_instructions(includes), before=True) - - ## Update arguments if we found any - for key, val in instructions['args'].items(): - args[key] = val - - if 'args' in instructions: - ## TODO: Reuseable code, there's to many get_instructions, merge_dictgs and args updating going on. - ## Update arguments if we found any - for key, val in instructions['args'].items(): - args[key] = val - - for key in args: - if args[key] == '': args[key] = input(f'Enter a value for {key}: ') - elif args[key] == '': args[key] = random_string(32) - elif args[key] == '': - args[key] = gen_yubikey_password() - if not args[key]: - print('[E] Failed to setup a yubikey password, is it plugged in?') - exit(1) - -# if args['password'] == '': args['password'] = input('Enter a disk (and root) password: ') -# elif args['password'] == '': -# args['password'] = gen_yubikey_password() -# if not args['password']: + # TODO: Might not need to return anything here, passed by reference? + instructions = merge_in_includes(instructions) + cleanup_args() print(json.dumps(args, indent=4)) if args['default'] and not 'force' in args: -- cgit v1.2.3-70-g09d2 From 5f256b9e4afc7c7a604c8c240033ab8eba2b6467 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 17 Nov 2019 13:56:18 +0000 Subject: Added tests. Also improved emulated commands. --- archinstall.py | 261 +++++++++++++++++++++++++++------------------------- test_archinstall.py | 13 +++ 2 files changed, 151 insertions(+), 123 deletions(-) create mode 100644 test_archinstall.py diff --git a/archinstall.py b/archinstall.py index 1d0bba3d..5c261662 100644 --- a/archinstall.py +++ b/archinstall.py @@ -2,15 +2,16 @@ import traceback import os, re, struct, sys, json, pty, shlex import urllib.request, urllib.parse, ssl, signal +import time from glob import glob from select import epoll, EPOLLIN, EPOLLHUP from socket import socket, inet_ntoa, AF_INET, AF_INET6, AF_PACKET from collections import OrderedDict as oDict from subprocess import Popen, STDOUT, PIPE -from time import sleep, time from random import choice from string import ascii_uppercase, ascii_lowercase, digits from hashlib import sha512 +from threading import Thread, enumerate as tenum if not os.path.isdir('/sys/firmware/efi'): print('[E] This script only supports UEFI-booted machines.') @@ -24,8 +25,9 @@ else: profiles_path = 'https://raw.githubusercontent.com/Torxed/archinstall/master/deployments' rootdir_pattern = re.compile('^.*?/devices') harddrives = oDict() -commandlog = oDict() -instructions = +commandlog = [] +worker_history = oDict() +instructions = oDict() args = {} positionals = [] for arg in sys.argv[1:]: @@ -61,6 +63,8 @@ class LOG_LEVELS: INFO = 4 DEBUG = 5 +LOG_LEVEL = 4 + def log(*msg, origin='UNKNOWN', level=5, **kwargs): if level <= LOG_LEVEL: msg = [item.decode('UTF-8', errors='backslashreplace') if type(item) == bytes else item for item in msg] @@ -102,7 +106,7 @@ except: self.interface = interface self.bytes_recv = int(bytes_recv) self.bytes_sent = int(bytes_sent) - def __repr__(self, *args, **kwargs): + def __repr__(self, *positionals, **kwargs): return f'iostat@{self.interface}[bytes_sent: {self.bytes_sent}, bytes_recv: {self.bytes_recv}]' class psutil(): @@ -152,7 +156,7 @@ signal.signal(signal.SIGINT, sig_handler) def gen_uid(entropy_length=256): return sha512(os.urandom(entropy_length)).hexdigest() -def get_default_gateway_linux(): +def get_default_gateway_linux(*args, **kwargs): """Read the default gateway directly from /proc.""" with open("/proc/net/route") as fh: for line in fh: @@ -185,12 +189,33 @@ def pid_exists(pid): else: return True -class sys_command(Thread): - def __init__(self, cmd, callback=None, start_callback=None, *args, **kwargs): +def simple_command(cmd, opts=None, *positionals, **kwargs): + if not opts: opts = {} + if 'debug' in opts: + print('[!] {}'.format(cmd)) + handle = Popen(cmd, shell='True', stdout=PIPE, stderr=STDOUT, stdin=PIPE, **kwargs) + output = b'' + while handle.poll() is None: + data = handle.stdout.read() + if len(data): + if 'debug' in opts: + print(data.decode('UTF-8'), end='') + # print(data.decode('UTF-8'), end='') + output += data + data = handle.stdout.read() + if 'debug' in opts: + print(data.decode('UTF-8'), end='') + output += data + handle.stdin.close() + handle.stdout.close() + return output + +class sys_command():#Thread): + def __init__(self, cmd, callback=None, start_callback=None, *positionals, **kwargs): if not 'worker_id' in kwargs: kwargs['worker_id'] = gen_uid() if not 'emulate' in kwargs: kwargs['emulate'] = SAFETY_LOCK - Thread.__init__(self) - if self.kwargs['emulate']: + #Thread.__init__(self) + if kwargs['emulate']: print('Starting command in emulation mode.') self.cmd = shlex.split(cmd) self.args = args @@ -206,24 +231,32 @@ class sys_command(Thread): user_catalogue = os.path.expanduser('~') self.cwd = f"{user_catalogue}/archinstall/cache/workers/{kwargs['worker_id']}/" - self.exec_dir = f'{self.cwd}/{basename(self.cmd[0])}_workingdir' + self.exec_dir = f'{self.cwd}/{os.path.basename(self.cmd[0])}_workingdir' if not self.cmd[0][0] == '/': log('Worker command is not executed with absolute path, trying to find: {}'.format(self.cmd[0]), origin='spawn', level=5) - o = b''.join(sys_command('/usr/bin/which {}'.format(self.cmd[0])).exec()) + o = sys_command('/usr/bin/which {}'.format(self.cmd[0]), emulate=False) log('This is the binary {} for {}'.format(o.decode('UTF-8'), self.cmd[0]), origin='spawn', level=5) self.cmd[0] = o.decode('UTF-8') - if not isdir(self.exec_dir): + if not os.path.isdir(self.exec_dir): os.makedirs(self.exec_dir) commandlog.append(cmd + ' #emulated') - if start_callback: start_callback(self, *args, **kwargs) - self.start() + if start_callback: start_callback(self, *positionals, **kwargs) + #self.start() + self.run() - def __repr__(self, *args, **kwargs): + def __iter__(self, *positionals, **kwargs): + for line in self.trace_log.split(b'\n'): + yield line + + def __repr__(self, *positionals, **kwargs): return self.trace_log.decode('UTF-8') + def decode(self, fmt='UTF-8'): + return self.trace_log.decode(fmt) + def dump(self): return { 'status' : self.status, @@ -237,15 +270,15 @@ class sys_command(Thread): } def run(self): - main = None - for t in tenum(): - if t.name == 'MainThread': - main = t - break - - if not main: - print('Main thread not existing') - return + #main = None + #for t in tenum(): + # if t.name == 'MainThread': + # main = t + # break + + #if not main: + # print('Main thread not existing') + # return self.status = 'running' old_dir = os.getcwd() @@ -262,7 +295,7 @@ class sys_command(Thread): alive = True last_trigger_pos = 0 - while alive and main and main.isAlive() and not self.kwargs['emulate']: + while alive and not self.kwargs['emulate']: for fileno, event in poller.poll(0.1): try: output = os.read(child_fd, 8192).strip() @@ -344,27 +377,6 @@ class sys_command(Thread): if self.callback: self.callback(self, *self.args, **self.kwargs) -def simple_command(cmd, opts=None, *args, **kwargs): - if not opts: opts = {} - if 'debug' in opts: - print('[!] {}'.format(cmd)) - handle = Popen(cmd, shell='True', stdout=PIPE, stderr=STDOUT, stdin=PIPE, **kwargs) - output = b'' - while handle.poll() is None: - data = handle.stdout.read() - if len(data): - if 'debug' in opts: - print(data.decode('UTF-8'), end='') - # print(data.decode('UTF-8'), end='') - output += data - data = handle.stdout.read() - if 'debug' in opts: - print(data.decode('UTF-8'), end='') - output += data - handle.stdin.close() - handle.stdout.close() - return output - def get_drive_from_uuid(uuid): if len(harddrives) <= 0: raise ValueError("No hard drives to iterate in order to find: {}".format(uuid)) @@ -429,7 +441,7 @@ def update_git(branch='master'): os.execv('/usr/bin/python3', ['archinstall.py'] + sys.argv + ['--rebooted',]) extit(1) -def device_state(name): +def device_state(name, *positionals, **kwargs): # Based out of: https://askubuntu.com/questions/528690/how-to-get-list-of-all-non-removable-disk-device-names-ssd-hdd-and-sata-ide-onl/528709#528709 if os.path.isfile('/sys/block/{}/device/block/{}/removable'.format(name, name)): with open('/sys/block/{}/device/block/{}/removable'.format(name, name)) as f: @@ -449,8 +461,8 @@ def device_state(name): def get_partitions(dev): drive_name = os.path.basename(dev) parts = oDict() - #o = b''.join(sys_command('/usr/bin/lsblk -o name -J -b {dev}'.format(dev=dev)).exec()) - o = b''.join(sys_command('/usr/bin/lsblk -J {dev}'.format(dev=dev)).exec()) + #o = b''.join(sys_command('/usr/bin/lsblk -o name -J -b {dev}'.format(dev=dev))) + o = b''.join(sys_command('/usr/bin/lsblk -J {dev}'.format(dev=dev))) if b'not a block device' in o: ## TODO: Replace o = sys_command() with code, o = sys_command() ## and make sys_command() return the exit-code, way safer than checking output strings :P @@ -481,8 +493,8 @@ def get_disk_size(drive): with open(f'/sys/block/{dev_short_name}/device/block/{dev_short_name}/size', 'rb') as fh: return ''.join(human_readable_size(fh.read().decode('UTF-8').strip())) -def disk_info(drive): - info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}').exec()).decode('UTF_8'))['blockdevices'][0] +def disk_info(drive, *positionals, **kwargs): + info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}', *positionals, **kwargs)).decode('UTF_8'))['blockdevices'][0] fileformats = [] labels = [] for child in info['children']: @@ -506,7 +518,7 @@ def cleanup_args(): print('[E] Failed to setup a yubikey password, is it plugged in?') exit(1) -def merge_in_includes(instructions): +def merge_in_includes(instructions, *positionals, **kwargs): if 'args' in instructions: ## == Recursively fetch instructions if "include" is found under {args: ...} while 'include' in instructions['args']: @@ -515,9 +527,9 @@ def merge_in_includes(instructions): del(instructions['args']['include']) if type(includes) in (dict, list): for include in includes: - instructions = merge_dicts(instructions, get_instructions(include), before=True) + instructions = merge_dicts(instructions, get_instructions(include, *positionals, **kwargs), before=True) else: - instructions = merge_dicts(instructions, get_instructions(includes), before=True) + instructions = merge_dicts(instructions, get_instructions(includes), *positionals, **kwargs, before=True) ## Update arguments if we found any for key, val in instructions['args'].items(): @@ -532,12 +544,12 @@ def merge_in_includes(instructions): return instructions -def update_drive_list(): +def update_drive_list(*args, **kwargs): # https://github.com/karelzak/util-linux/blob/f920f73d83f8fd52e7a14ec0385f61fab448b491/disk-utils/fdisk-list.c#L52 for path in glob('/sys/block/*/device'): name = re.sub('.*/(.*?)/device', '\g<1>', path) - if device_state(name): - harddrives[f'/dev/{name}'] = disk_info(f'/dev/{name}') + if device_state(name, *positionals, **kwargs): + harddrives[f'/dev/{name}'] = disk_info(f'/dev/{name}', *positionals, **kwargs) def human_readable_size(bits, sizes=[{8 : 'b'}, {1024 : 'kb'}, {1024 : 'mb'}, {1024 : 'gb'}, {1024 : 'tb'}, {1024 : 'zb?'}]): # Not needed if using lsblk. @@ -567,12 +579,12 @@ def format_disk(drive, start='512MiB', end='100%', emulate=False): print(f'[N] Setting up {drive}.') # dd if=/dev/random of=args['drive'] bs=4096 status=progress # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate).exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}', emulate=emulate).exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate).exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate).exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate).exec()) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {size}', emulate=emulate).exec()) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate)) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}', emulate=emulate)) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate)) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate)) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate)) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {size}', emulate=emulate)) # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P @@ -605,8 +617,7 @@ def get_application_instructions(target): instructions = grab_url_data('{}/applications/{}.json'.format(args['profiles-path'], target)).decode('UTF-8') print('[N] Found application instructions for: {}'.format(target)) except urllib.error.HTTPError: - print('[N] No instructions found for: {}'.format(target)) - print('[N] Trying local instructions under ./deployments/applications') + print('[N] Could not find remote instructions. yrying local instructions under ./deployments/applications') local_path = './deployments/applications' if os.path.isfile('./archinstall.py') else './archinstall/deployments/applications' # Dangerous assumption if os.path.isfile(f'{local_path}/{target}.json'): with open(f'{local_path}/{target}.json', 'r') as fh: @@ -614,6 +625,7 @@ def get_application_instructions(target): print('[N] Found local application instructions for: {}'.format(target)) else: + print('[N] No instructions found for: {}'.format(target)) return instructions try: @@ -625,14 +637,13 @@ def get_application_instructions(target): return instructions -def get_instructions(target): +def get_instructions(target, *positionals, **kwargs): instructions = oDict() try: instructions = grab_url_data('{}/{}.json'.format(args['profiles-path'], target)).decode('UTF-8') print('[N] Found net-deploy instructions called: {}'.format(target)) except urllib.error.HTTPError: - print('[N] No instructions found called: {}'.format(target)) - print('[N] Trying local instructions under ./deployments') + print('[N] Could not find remote instructions. Trying local instructions under ./deployments') local_path = './deployments' if os.path.isfile('./archinstall.py') else './archinstall/deployments' # Dangerous assumption if os.path.isfile(f'{local_path}/{target}.json'): with open(f'{local_path}/{target}.json', 'r') as fh: @@ -640,6 +651,7 @@ def get_instructions(target): print('[N] Found local instructions called: {}'.format(target)) else: + print('[N] No instructions found called: {}'.format(target)) return instructions try: @@ -671,7 +683,7 @@ def merge_dicts(d1, d2, before=True, overwrite=False): def random_string(l): return ''.join(choice(ascii_uppercase + ascii_lowercase + digits) for i in range(l)) -def setup_args_defaults(args): +def setup_args_defaults(args, interactive=True): if not 'size' in args: args['size'] = '100%' if not 'start' in args: args['start'] = '513MiB' if not 'pwfile' in args: args['pwfile'] = '/tmp/diskpw' @@ -688,18 +700,21 @@ def setup_args_defaults(args): if not 'ignore-rerun' in args: args['ignore-rerun'] = False if not 'localtime' in args: args['localtime'] = 'Europe/Stockholm' if args['country'] == 'SE' else 'GMT+0' # TODO: Arbitrary for now if not 'drive' in args: - drives = sorted(list(harddrives.keys())) - if len(drives) > 1 and 'force' not in args and ('default' in args and 'first-drive' not in args): - for index, drive in enumerate(drives): - print(f'{index}: {drive} ({harddrives[drive]})') - drive = input('Select one of the above disks (by number): ') - if not drive.isdigit(): - raise KeyError("Multiple disks found, --drive=/dev/X not specified (or --force/--first-drive)") - drives = [drives[int(drive)]] # Make sure only the selected drive is in the list of options - args['drive'] = drives[0] # First drive found + if interactive: + drives = sorted(list(harddrives.keys())) + if len(drives) > 1 and 'force' not in args and ('default' in args and 'first-drive' not in args): + for index, drive in enumerate(drives): + print(f"{index}: {drive} ({harddrives[drive]['size'], harddrives[drive]['fstype'], harddrives[drive]['label']})") + drive = input('Select one of the above disks (by number): ') + if not drive.isdigit(): + raise KeyError("Multiple disks found, --drive=/dev/X not specified (or --force/--first-drive)") + drives = [drives[int(drive)]] # Make sure only the selected drive is in the list of options + args['drive'] = drives[0] # First drive found + else: + args['drive'] = None rerun = args['ignore-rerun'] - if args['drive'][0] != '/': + if args['drive'] and args['drive'][0] != '/': ## Remap the selected UUID to the device to be formatted. drive = get_drive_from_uuid(args['drive']) if not drive: @@ -713,15 +728,15 @@ def setup_args_defaults(args): args['drive'] = drive return args -def load_automatic_instructions(): +def load_automatic_instructions(*args, **kwargs): instructions = oDict() - if get_default_gateway_linux(): + if get_default_gateway_linux(*args, **kwargs): locmac = get_local_MACs() if not len(locmac): print('[N] No network interfaces - No net deploy.') else: for mac in locmac: - instructions = get_instructions(mac) + instructions = get_instructions(mac, *positionals, **kwargs) if 'args' in instructions: ## == Recursively fetch instructions if "include" is found under {args: ...} @@ -731,9 +746,9 @@ def load_automatic_instructions(): del(instructions['args']['include']) if type(includes) in (dict, list): for include in includes: - instructions = merge_dicts(instructions, get_instructions(include), before=True) + instructions = merge_dicts(instructions, get_instructions(include, *positionals, **kwargs), before=True) else: - instructions = merge_dicts(instructions, get_instructions(includes), before=True) + instructions = merge_dicts(instructions, get_instructions(includes, *positionals, **kwargs), before=True) ## Update arguments if we found any for key, val in instructions['args'].items(): @@ -799,7 +814,7 @@ if __name__ == '__main__': if not args['rerun'] or args['ignore-rerun']: for i in range(5, 0, -1): print(f'Formatting {args["drive"]} in {i}...') - sleep(1) + time.sleep(1) close_disks() format_disk(args['drive'], start=args['start'], end=args['size']) @@ -816,7 +831,7 @@ if __name__ == '__main__': print(json.dumps(args['paritions'][part_name], indent=4)) if not args['rerun'] or args['ignore-rerun']: - o = b''.join(sys_command('/usr/bin/mkfs.vfat -F32 {drive}{partition_1}'.format(**args)).exec()) + o = b''.join(sys_command('/usr/bin/mkfs.vfat -F32 {drive}{partition_1}'.format(**args))) if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: print('[E] Could not setup {drive}{partition_1}'.format(**args), o) exit(1) @@ -824,34 +839,34 @@ if __name__ == '__main__': # "--cipher sha512" breaks the shit. # TODO: --use-random instead of --use-urandom print('[N] Adding encryption to {drive}{partition_2}.'.format(**args)) - o = b''.join(sys_command('/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {pwfile} --use-urandom luksFormat {drive}{partition_2}'.format(**args)).exec()) + o = b''.join(sys_command('/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {pwfile} --use-urandom luksFormat {drive}{partition_2}'.format(**args))) if not b'Command successful.' in o: print('[E] Failed to setup disk encryption.', o) exit(1) - o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev').exec()) # /dev/dm-0 + o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev')) # /dev/dm-0 if b'cannot open' in o: - o = b''.join(sys_command('/usr/bin/cryptsetup open {drive}{partition_2} luksdev --key-file {pwfile} --type luks2'.format(**args)).exec()) - o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev').exec()) # /dev/dm-0 + o = b''.join(sys_command('/usr/bin/cryptsetup open {drive}{partition_2} luksdev --key-file {pwfile} --type luks2'.format(**args))) + o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev')) # /dev/dm-0 if b'cannot open' in o: print('[E] Could not open encrypted device.', o) exit(1) if not args['rerun'] or args['ignore-rerun']: print('[N] Creating btrfs filesystem inside {drive}{partition_2}'.format(**args)) - o = b''.join(sys_command('/usr/bin/mkfs.btrfs -f /dev/mapper/luksdev').exec()) + o = b''.join(sys_command('/usr/bin/mkfs.btrfs -f /dev/mapper/luksdev')) if not b'UUID' in o: print('[E] Could not setup btrfs filesystem.', o) exit(1) o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt') # /dev/dm-0 if len(o) <= 0: - o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt').exec()) + o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt')) os.makedirs('/mnt/boot', exist_ok=True) o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot') # /dev/dm-0 if len(o) <= 0: - o = b''.join(sys_command('/usr/bin/mount {drive}{partition_1} /mnt/boot'.format(**args)).exec()) + o = b''.join(sys_command('/usr/bin/mount {drive}{partition_1} /mnt/boot'.format(**args))) if 'mirrors' in args and args['mirrors'] and 'country' in args and get_default_gateway_linux(): print('[N] Reordering mirrors.') @@ -899,7 +914,7 @@ if __name__ == '__main__': print('[-] Options: {}'.format(opts)) #print('[N] Command: {} ({})'.format(raw_command, opts)) - o = b''.join(sys_command('{c}'.format(c=command), opts).exec()) + o = b''.join(sys_command('{c}'.format(c=command), opts)) if type(conf[title][raw_command]) == bytes and len(conf[title][raw_command]) and not conf[title][raw_command] in b''.join(o): print('[W] Prerequisit step failed: {}'.format(b''.join(o).decode('UTF-8'))) #print(o) @@ -908,28 +923,28 @@ if __name__ == '__main__': print('[N] Straping in packages.') if args['aur-support']: args['packages'] += ' git' - o = b''.join(sys_command('/usr/bin/pacman -Syy').exec()) - o = b''.join(sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args)).exec()) + o = b''.join(sys_command('/usr/bin/pacman -Syy')) + o = b''.join(sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args))) if not os.path.isdir('/mnt/etc'): # TODO: This might not be the most long term stable thing to rely on... print('[E] Failed to strap in packages', o) exit(1) if not args['rerun'] or rerun: - o = b''.join(sys_command('/usr/bin/genfstab -pU /mnt >> /mnt/etc/fstab').exec()) + o = b''.join(sys_command('/usr/bin/genfstab -pU /mnt >> /mnt/etc/fstab')) with open('/mnt/etc/fstab', 'a') as fstab: fstab.write('\ntmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0\n') # Redundant \n at the start? who knoes? - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt rm -f /etc/localtime').exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt ln -s /usr/share/zoneinfo/{localtime} /etc/localtime'.format(**args)).exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime').exec()) - #o = sys_command('arch-chroot /mnt echo "{hostname}" > /etc/hostname'.format(**args)).exec() - #o = sys_command("arch-chroot /mnt sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen").exec() - o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo '{hostname}' > /etc/hostname\"".format(**args)).exec()) - o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen\"").exec()) - o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'LANG=en_US.UTF-8' > /etc/locale.conf\"").exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt locale-gen').exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt chmod 700 /root').exec()) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt rm -f /etc/localtime')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt ln -s /usr/share/zoneinfo/{localtime} /etc/localtime'.format(**args))) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime')) + #o = sys_command('arch-chroot /mnt echo "{hostname}" > /etc/hostname'.format(**args)) + #o = sys_command("arch-chroot /mnt sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen") + o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo '{hostname}' > /etc/hostname\"".format(**args))) + o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen\"")) + o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'LANG=en_US.UTF-8' > /etc/locale.conf\"")) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt locale-gen')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt chmod 700 /root')) with open('/mnt/etc/mkinitcpio.conf', 'w') as mkinit: ## TODO: Don't replace it, in case some update in the future actually adds something. @@ -937,9 +952,9 @@ if __name__ == '__main__': mkinit.write('BINARIES=(/usr/bin/btrfs)\n') mkinit.write('FILES=()\n') mkinit.write('HOOKS=(base udev autodetect modconf block encrypt filesystems keyboard fsck)\n') - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt mkinitcpio -p linux').exec()) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt mkinitcpio -p linux')) ## WORKAROUND: https://github.com/systemd/systemd/issues/13603#issuecomment-552246188 - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt bootctl --no-variables --path=/boot install').exec()) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt bootctl --no-variables --path=/boot install')) with open('/mnt/boot/loader/loader.conf', 'w') as loader: loader.write('default arch\n') @@ -947,7 +962,7 @@ if __name__ == '__main__': ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. ## And blkid is wrong in terms of LUKS. - #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').exec().strip() + #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() UUID = simple_command("ls -l /dev/disk/by-uuid/ | grep {basename}{partition_2} | awk '{{print $9}}'".format(basename=os.path.basename(args['drive']), **args)).decode('UTF-8').strip() with open('/mnt/boot/loader/entries/arch.conf', 'w') as entry: entry.write('title Arch Linux\n') @@ -957,16 +972,16 @@ if __name__ == '__main__': if args['aur-support']: print('[N] AUR support demanded, building "yay" before running POST steps.') - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "useradd -m -G wheel aibuilder"').exec()) - o = b''.join(sys_command("/usr/bin/sed -i 's/# %wheel ALL=(ALL) NO/%wheel ALL=(ALL) NO/' /mnt/etc/sudoers").exec()) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "useradd -m -G wheel aibuilder"')) + o = b''.join(sys_command("/usr/bin/sed -i 's/# %wheel ALL=(ALL) NO/%wheel ALL=(ALL) NO/' /mnt/etc/sudoers")) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder; git clone https://aur.archlinux.org/yay.git)\\""').exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "chown -R aibuilder.aibuilder /home/aibuilder/yay"').exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder/yay; makepkg -si --noconfirm)\\" >/dev/null"').exec()) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder; git clone https://aur.archlinux.org/yay.git)\\""')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "chown -R aibuilder.aibuilder /home/aibuilder/yay"')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder/yay; makepkg -si --noconfirm)\\" >/dev/null"')) ## Do not remove aibuilder just yet, can be used later for aur packages. - #o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers').exec()) - #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"').exec()) - #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"').exec()) + #o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers')) + #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"')) + #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"')) print('[N] AUR support added. use "yay -Syy --noconfirm " to deploy in POST.') conf = {} @@ -1057,20 +1072,20 @@ if __name__ == '__main__': bytes(f'login:', 'UTF-8') : b'root\n', #b'Password:' : bytes(args['password']+'\n', 'UTF-8'), bytes(f'[root@{args["hostname"]} ~]#', 'UTF-8') : bytes(command+'\n', 'UTF-8'), - }, **opts}).exec()) + }, **opts})) ## Not needed anymore: And cleanup after out selves.. Don't want to leave any residue.. # os.remove('/mnt/etc/systemd/system/console-getty.service.d/override.conf') else: - o = b''.join(sys_command('/usr/bin/systemd-nspawn -D /mnt --machine temporary {c}'.format(c=command), opts=opts).exec()) + o = b''.join(sys_command('/usr/bin/systemd-nspawn -D /mnt --machine temporary {c}'.format(c=command), opts=opts)) if type(conf[title][raw_command]) == bytes and len(conf[title][raw_command]) and not conf[title][raw_command] in o: print('[W] Post install command failed: {}'.format(o.decode('UTF-8'))) #print(o) if args['aur-support']: - o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers').exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"').exec()) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"').exec()) + o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"')) ## == Passwords # o = sys_command('arch-chroot /mnt usermod --password {} root'.format(args['password'])) diff --git a/test_archinstall.py b/test_archinstall.py new file mode 100644 index 00000000..3b5ddcae --- /dev/null +++ b/test_archinstall.py @@ -0,0 +1,13 @@ +import json +import archinstall + +archinstall.update_drive_list(emulate=False) +archinstall.setup_args_defaults(archinstall.args, interactive=False) +#for drive in archinstall.harddrives: +# print(drive, archinstall.human_disk_info(drive)) + +instructions = archinstall.load_automatic_instructions(emulate=False) +profile_instructions = archinstall.get_instructions('workstation', emulate=False) +profile_instructions = archinstall.merge_in_includes(profile_instructions, emulate=False) + +print(json.dumps(archinstall.args, indent=4)) \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 9cd0a4b73f4d284e1991360f316a1053a234f232 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 17 Nov 2019 23:06:09 +0000 Subject: Fixed some stuff --- archinstall.py | 7 +++++-- test_archinstall.py | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index 5c261662..e43109b4 100644 --- a/archinstall.py +++ b/archinstall.py @@ -216,7 +216,7 @@ class sys_command():#Thread): if not 'emulate' in kwargs: kwargs['emulate'] = SAFETY_LOCK #Thread.__init__(self) if kwargs['emulate']: - print('Starting command in emulation mode.') + print(f"Starting command '{cmd}' in emulation mode.") self.cmd = shlex.split(cmd) self.args = args self.kwargs = kwargs @@ -494,7 +494,10 @@ def get_disk_size(drive): return ''.join(human_readable_size(fh.read().decode('UTF-8').strip())) def disk_info(drive, *positionals, **kwargs): - info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}', *positionals, **kwargs)).decode('UTF_8'))['blockdevices'][0] + lkwargs = {**kwargs} + lkwargs['emulate'] = False # This is a emulate-safe function. Does not alter filesystem. + + info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}', *positionals, **lkwargs)).decode('UTF_8'))['blockdevices'][0] fileformats = [] labels = [] for child in info['children']: diff --git a/test_archinstall.py b/test_archinstall.py index 3b5ddcae..30bc76e7 100644 --- a/test_archinstall.py +++ b/test_archinstall.py @@ -9,5 +9,6 @@ archinstall.setup_args_defaults(archinstall.args, interactive=False) instructions = archinstall.load_automatic_instructions(emulate=False) profile_instructions = archinstall.get_instructions('workstation', emulate=False) profile_instructions = archinstall.merge_in_includes(profile_instructions, emulate=False) +archinstall.args['password'] = 'test' print(json.dumps(archinstall.args, indent=4)) \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 252dfb295b271cd3f7cbc0cf99bf190f3a620225 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 16:42:02 +0100 Subject: Fix for unpartitioned drives. --- archinstall.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/archinstall.py b/archinstall.py index e43109b4..26c82a7e 100644 --- a/archinstall.py +++ b/archinstall.py @@ -500,11 +500,12 @@ def disk_info(drive, *positionals, **kwargs): info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}', *positionals, **lkwargs)).decode('UTF_8'))['blockdevices'][0] fileformats = [] labels = [] - for child in info['children']: - if child['fstype'] != None: - fileformats.append(child['fstype']) - if child['label'] != None: - labels.append(child['label']) + if 'children' in info: ## Might not be partitioned yet + for child in info['children']: + if child['fstype'] != None: + fileformats.append(child['fstype']) + if child['label'] != None: + labels.append(child['label']) info['fileformats'] = fileformats info['labels'] = labels info['model'] = get_disk_model(drive) -- cgit v1.2.3-70-g09d2 From c7bcba7a6a04abaca49dba8306eb08e76dfa937f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 16:48:37 +0100 Subject: More verbose output for unformatted drives. --- archinstall.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/archinstall.py b/archinstall.py index 26c82a7e..6ca0e1c9 100644 --- a/archinstall.py +++ b/archinstall.py @@ -506,6 +506,8 @@ def disk_info(drive, *positionals, **kwargs): fileformats.append(child['fstype']) if child['label'] != None: labels.append(child['label']) + else: + labels = ['*Empty drive (no partitions)*'] info['fileformats'] = fileformats info['labels'] = labels info['model'] = get_disk_model(drive) -- cgit v1.2.3-70-g09d2 From 11d1e0f89c66d118aadafffa2f29dbad22e870d9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 16:50:05 +0100 Subject: More visible output --- archinstall.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 6ca0e1c9..a57c4722 100644 --- a/archinstall.py +++ b/archinstall.py @@ -507,7 +507,8 @@ def disk_info(drive, *positionals, **kwargs): if child['label'] != None: labels.append(child['label']) else: - labels = ['*Empty drive (no partitions)*'] + fileformats = ['*Empty Drive*'] + labels = ['(no partitions)'] info['fileformats'] = fileformats info['labels'] = labels info['model'] = get_disk_model(drive) -- cgit v1.2.3-70-g09d2 From ece0b764bca7c9f66af31c63b0599a972ae5560d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 16:51:17 +0100 Subject: Corrected commandlog history emulated or not --- archinstall.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index a57c4722..ae4ad9c9 100644 --- a/archinstall.py +++ b/archinstall.py @@ -242,7 +242,10 @@ class sys_command():#Thread): if not os.path.isdir(self.exec_dir): os.makedirs(self.exec_dir) - commandlog.append(cmd + ' #emulated') + if self.kwargs['emulate']: + commandlog.append(cmd + ' #emulated') + else: + commandlog.append(cmd) if start_callback: start_callback(self, *positionals, **kwargs) #self.start() self.run() -- cgit v1.2.3-70-g09d2 From 7f59f0fdd64bbcb010c5e12ccefeb05cbf1600dc Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 17:02:53 +0100 Subject: Test --- archinstall.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index ae4ad9c9..3ef0d2b4 100644 --- a/archinstall.py +++ b/archinstall.py @@ -235,7 +235,7 @@ class sys_command():#Thread): if not self.cmd[0][0] == '/': log('Worker command is not executed with absolute path, trying to find: {}'.format(self.cmd[0]), origin='spawn', level=5) - o = sys_command('/usr/bin/which {}'.format(self.cmd[0]), emulate=False) + o = sys_command('/usr/bin/which {}'.format(self.cmd[0]), emulate=False, hide_from_log=True) log('This is the binary {} for {}'.format(o.decode('UTF-8'), self.cmd[0]), origin='spawn', level=5) self.cmd[0] = o.decode('UTF-8') @@ -244,6 +244,8 @@ class sys_command():#Thread): if self.kwargs['emulate']: commandlog.append(cmd + ' #emulated') + elif 'hide_from_log' in self.kwargs and self.kwargs['hide_from_log']: + pass else: commandlog.append(cmd) if start_callback: start_callback(self, *positionals, **kwargs) @@ -465,7 +467,7 @@ def get_partitions(dev): drive_name = os.path.basename(dev) parts = oDict() #o = b''.join(sys_command('/usr/bin/lsblk -o name -J -b {dev}'.format(dev=dev))) - o = b''.join(sys_command('/usr/bin/lsblk -J {dev}'.format(dev=dev))) + o = b''.join(sys_command(f'/usr/bin/lsblk -J {dev}', hide_from_log=True)) if b'not a block device' in o: ## TODO: Replace o = sys_command() with code, o = sys_command() ## and make sys_command() return the exit-code, way safer than checking output strings :P -- cgit v1.2.3-70-g09d2 From f679b49070a9a5339ed36b066f038bf3812414f1 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 17:08:26 +0100 Subject: Cache password is now a function. This is so others can call it --- archinstall.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/archinstall.py b/archinstall.py index 3ef0d2b4..26de5215 100644 --- a/archinstall.py +++ b/archinstall.py @@ -770,6 +770,12 @@ def load_automatic_instructions(*args, **kwargs): return instructions +def cache_diskpw_on_disk(): + if not os.path.isfile(args['pwfile']): + #PIN = '0000' + with open(args['pwfile'], 'w') as pw: + pw.write(args['password']) + if __name__ == '__main__': update_git() # Breaks and restarts the script if an update was found. update_drive_list() @@ -809,10 +815,7 @@ if __name__ == '__main__': if(input('Are these settings OK? (No return beyond this point) N/y: ').lower() != 'y'): exit(1) - if not os.path.isfile(args['pwfile']): - #PIN = '0000' - with open(args['pwfile'], 'w') as pw: - pw.write(args['password']) + cache_diskpw_on_disk() #else: # ## TODO: Convert to `rb` instead. # # We shouldn't discriminate \xfu from being a passwd phrase. -- cgit v1.2.3-70-g09d2 From ac8393645c49d0c11170566d7a1650b2da906567 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 17:11:45 +0100 Subject: Don't show drives unless we have some --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 26de5215..040b29b5 100644 --- a/archinstall.py +++ b/archinstall.py @@ -712,7 +712,7 @@ def setup_args_defaults(args, interactive=True): if not 'ignore-rerun' in args: args['ignore-rerun'] = False if not 'localtime' in args: args['localtime'] = 'Europe/Stockholm' if args['country'] == 'SE' else 'GMT+0' # TODO: Arbitrary for now if not 'drive' in args: - if interactive: + if interactive and len(harddrives): drives = sorted(list(harddrives.keys())) if len(drives) > 1 and 'force' not in args and ('default' in args and 'first-drive' not in args): for index, drive in enumerate(drives): -- cgit v1.2.3-70-g09d2 From 27059f4f803c1eeefce54308a271e69092bea8ab Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 17:15:15 +0100 Subject: Added debug --- archinstall.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 040b29b5..311cc420 100644 --- a/archinstall.py +++ b/archinstall.py @@ -587,7 +587,9 @@ def close_disks(): o = simple_command('/usr/bin/umount -R /mnt') o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') -def format_disk(drive, start='512MiB', end='100%', emulate=False): +def format_disk(drive=None, start='512MiB', end='100%', emulate=False): + if not drive: + raise ValueError('Need to supply a drive path, for instance: /dev/sdx') print(f'[N] Setting up {drive}.') # dd if=/dev/random of=args['drive'] bs=4096 status=progress # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda -- cgit v1.2.3-70-g09d2 From 997baca5fcc39a12e56d01bffb6ac6e970e8d855 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 17:17:58 +0100 Subject: Added args, kwargs to a function --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 311cc420..b34632f0 100644 --- a/archinstall.py +++ b/archinstall.py @@ -587,7 +587,7 @@ def close_disks(): o = simple_command('/usr/bin/umount -R /mnt') o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') -def format_disk(drive=None, start='512MiB', end='100%', emulate=False): +def format_disk(drive=None, start='512MiB', end='100%', emulate=False, *args, **kwargs): if not drive: raise ValueError('Need to supply a drive path, for instance: /dev/sdx') print(f'[N] Setting up {drive}.') -- cgit v1.2.3-70-g09d2 From eb318c24db4f76395c8872ed33af2e68f2124bb1 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 17:18:50 +0100 Subject: Parameter missmatch on name --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index b34632f0..df63a08f 100644 --- a/archinstall.py +++ b/archinstall.py @@ -598,7 +598,7 @@ def format_disk(drive=None, start='512MiB', end='100%', emulate=False, *args, ** o = b''.join(sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate)) o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate)) o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate)) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {size}', emulate=emulate)) + o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {end}', emulate=emulate)) # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P -- cgit v1.2.3-70-g09d2 From 30752a49c6b7a394508aee381fcc293bad584aae Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:04:36 +0000 Subject: Added refreshing of partitions into a function --- archinstall.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index df63a08f..6b26059c 100644 --- a/archinstall.py +++ b/archinstall.py @@ -778,6 +778,9 @@ def cache_diskpw_on_disk(): with open(args['pwfile'], 'w') as pw: pw.write(args['password']) +def refresh_partition_list(drive): + args['paritions'] = get_partitions(drive) + if __name__ == '__main__': update_git() # Breaks and restarts the script if an update was found. update_drive_list() @@ -836,7 +839,7 @@ if __name__ == '__main__': close_disks() format_disk(args['drive'], start=args['start'], end=args['size']) - args['paritions'] = get_partitions(args['drive']) + refresh_partition_list(args['drive']) print(f'Partitions: (Boot: {list(args["paritions"].keys())[0]})') if len(args['paritions']) <= 0: -- cgit v1.2.3-70-g09d2 From da36b4f4e108369c91d8eb8ec1a7d26468c20010 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:09:18 +0000 Subject: Started adding failure responses on commands for error checks. --- archinstall.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/archinstall.py b/archinstall.py index 6b26059c..d9d5556f 100644 --- a/archinstall.py +++ b/archinstall.py @@ -593,16 +593,25 @@ def format_disk(drive=None, start='512MiB', end='100%', emulate=False, *args, ** print(f'[N] Setting up {drive}.') # dd if=/dev/random of=args['drive'] bs=4096 status=progress # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate)) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}', emulate=emulate)) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate)) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate)) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate)) - o = b''.join(sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {end}', emulate=emulate)) + if sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate).exit_code != 0: + return None + if sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate).exit_code != 0: + return None + if sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}', emulate=emulate).exit_code != 0: + return None + if sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate).exit_code != 0: + return None + if sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate).exit_code != 0: + return None + if sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate).exit_code != 0: + return None + if sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {end}', emulate=emulate).exit_code != 0: + return None # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P + def multisplit(s, splitters): s = [s,] for key in splitters: -- cgit v1.2.3-70-g09d2 From c2a2e1e5d07e4c2582c3063a57cd52e46a61edd7 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:09:57 +0000 Subject: Added success return on format of disks --- archinstall.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/archinstall.py b/archinstall.py index d9d5556f..bddf8de4 100644 --- a/archinstall.py +++ b/archinstall.py @@ -607,10 +607,12 @@ def format_disk(drive=None, start='512MiB', end='100%', emulate=False, *args, ** return None if sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {end}', emulate=emulate).exit_code != 0: return None + # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P + return True def multisplit(s, splitters): s = [s,] -- cgit v1.2.3-70-g09d2 From 1ae1c764ba194279c19428f64c50b9a8af0980aa Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:10:38 +0000 Subject: Added args/kwargs to function --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index bddf8de4..61a51e36 100644 --- a/archinstall.py +++ b/archinstall.py @@ -789,7 +789,7 @@ def cache_diskpw_on_disk(): with open(args['pwfile'], 'w') as pw: pw.write(args['password']) -def refresh_partition_list(drive): +def refresh_partition_list(drive, *args, **kwargs): args['paritions'] = get_partitions(drive) if __name__ == '__main__': -- cgit v1.2.3-70-g09d2 From 8c03f60765c1a9490d40b50181f599115ec7b70e Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:13:20 +0000 Subject: Stupid of me to call the sys.argv for args. Now I have to rename all *args expansions to *positionals or something --- archinstall.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/archinstall.py b/archinstall.py index 61a51e36..c03fd78e 100644 --- a/archinstall.py +++ b/archinstall.py @@ -156,7 +156,7 @@ signal.signal(signal.SIGINT, sig_handler) def gen_uid(entropy_length=256): return sha512(os.urandom(entropy_length)).hexdigest() -def get_default_gateway_linux(*args, **kwargs): +def get_default_gateway_linux(*positionals, **kwargs): """Read the default gateway directly from /proc.""" with open("/proc/net/route") as fh: for line in fh: @@ -556,7 +556,7 @@ def merge_in_includes(instructions, *positionals, **kwargs): return instructions -def update_drive_list(*args, **kwargs): +def update_drive_list(*positionals, **kwargs): # https://github.com/karelzak/util-linux/blob/f920f73d83f8fd52e7a14ec0385f61fab448b491/disk-utils/fdisk-list.c#L52 for path in glob('/sys/block/*/device'): name = re.sub('.*/(.*?)/device', '\g<1>', path) @@ -753,9 +753,9 @@ def setup_args_defaults(args, interactive=True): args['drive'] = drive return args -def load_automatic_instructions(*args, **kwargs): +def load_automatic_instructions(*positionals, **kwargs): instructions = oDict() - if get_default_gateway_linux(*args, **kwargs): + if get_default_gateway_linux(*positionals, **kwargs): locmac = get_local_MACs() if not len(locmac): print('[N] No network interfaces - No net deploy.') @@ -789,7 +789,7 @@ def cache_diskpw_on_disk(): with open(args['pwfile'], 'w') as pw: pw.write(args['password']) -def refresh_partition_list(drive, *args, **kwargs): +def refresh_partition_list(drive, *positionals, **kwargs): args['paritions'] = get_partitions(drive) if __name__ == '__main__': -- cgit v1.2.3-70-g09d2 From f5f1f210fe852dfdca3f42200e444d2a61d329c3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:14:56 +0000 Subject: Added more *q, **k to functions --- archinstall.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/archinstall.py b/archinstall.py index c03fd78e..b2716284 100644 --- a/archinstall.py +++ b/archinstall.py @@ -394,11 +394,11 @@ def get_drive_from_uuid(uuid): return None -def get_drive_from_part_uuid(partuuid): +def get_drive_from_part_uuid(partuuid, *positionals, **kwargs): if len(harddrives) <= 0: raise ValueError("No hard drives to iterate in order to find: {}".format(uuid)) for drive in harddrives: - for partition in get_partitions(f'/dev/{drive}'): + for partition in get_partitions(f'/dev/{drive}', *positionals, **kwargs): o = simple_command(f'blkid -s PARTUUID -o value /dev/{drive}') if len(o) and o == partuuid: return drive @@ -463,7 +463,7 @@ def device_state(name, *positionals, **kwargs): return return True -def get_partitions(dev): +def get_partitions(dev, *positionals, **kwargs): drive_name = os.path.basename(dev) parts = oDict() #o = b''.join(sys_command('/usr/bin/lsblk -o name -J -b {dev}'.format(dev=dev))) @@ -790,7 +790,8 @@ def cache_diskpw_on_disk(): pw.write(args['password']) def refresh_partition_list(drive, *positionals, **kwargs): - args['paritions'] = get_partitions(drive) + args['paritions'] = get_partitions(drive, *positionals, **kwargs) + return True if __name__ == '__main__': update_git() # Breaks and restarts the script if an update was found. -- cgit v1.2.3-70-g09d2 From 737c2b648d08816da78e3c5b818f1884d211fda9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:46:20 +0000 Subject: Cleaned up the entire format process into functions. --- archinstall.py | 72 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/archinstall.py b/archinstall.py index b2716284..2749458d 100644 --- a/archinstall.py +++ b/archinstall.py @@ -793,6 +793,52 @@ def refresh_partition_list(drive, *positionals, **kwargs): args['paritions'] = get_partitions(drive, *positionals, **kwargs) return True +def mkfs_fat32(drive, partition, *positionals, **kwargs): + o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {drive}{partition}')) + if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: + return None + return True + +def is_luksdev_mounted(*positionals, **kwargs): + o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev')) # /dev/dm-0 + if b'cannot open' in o: + return False + return True + +def mount_luktsdev(drive, partition, keyfile, *positionals, **kwargs): + if not is_luksdev_mounted(): + o = b''.join(sys_command(f'/usr/bin/cryptsetup open {drive}{partition} luksdev --key-file {keyfile} --type luks2'.format(**args))) + return is_luksdev_mounted() + +def encrypt_partition(drive, partition, keyfile='/tmp/diskpw', *positionals, **kwargs): + o = b''.join(sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {keyfile} --use-urandom luksFormat {drive}{partition}')) + if not b'Command successful.' in o: + return False + return True + +def mkfs_btrfs(drive='/dev/mapper/luksdev', *positionals, **kwargs): + o = b''.join(sys_command('/usr/bin/mkfs.btrfs -f /dev/mapper/luksdev')) + if not b'UUID' in o: + return False + return True + +def mount_luksdev(where='/dev/mapper/luksdev', to='/mnt', *positionals, **kwargs): + o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt') # /dev/dm-0 + if len(o) <= 0: + o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt')) + return True + +def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs) + os.makedirs('/mnt/boot', exist_ok=True) + o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot') # /dev/dm-0 + if len(o) <= 0: + o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}')) + return True + +def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot'): + mount_luksdev() + mount_boot(drive, bootpartition, mountpoint='/mnt/boot') + if __name__ == '__main__': update_git() # Breaks and restarts the script if an update was found. update_drive_list() @@ -863,42 +909,28 @@ if __name__ == '__main__': print(json.dumps(args['paritions'][part_name], indent=4)) if not args['rerun'] or args['ignore-rerun']: - o = b''.join(sys_command('/usr/bin/mkfs.vfat -F32 {drive}{partition_1}'.format(**args))) - if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: - print('[E] Could not setup {drive}{partition_1}'.format(**args), o) + if not mkfs_fat32(args['drive'], args['partition_1'], *positionals, **kwargs): + print('[E] Could not setup {drive}{partition_1}'.format(**args)) exit(1) # "--cipher sha512" breaks the shit. # TODO: --use-random instead of --use-urandom print('[N] Adding encryption to {drive}{partition_2}.'.format(**args)) - o = b''.join(sys_command('/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {pwfile} --use-urandom luksFormat {drive}{partition_2}'.format(**args))) - if not b'Command successful.' in o: + if not encrypt_partition(args['drive'], args['partition_2'], args['pwfile']): print('[E] Failed to setup disk encryption.', o) exit(1) - o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev')) # /dev/dm-0 - if b'cannot open' in o: - o = b''.join(sys_command('/usr/bin/cryptsetup open {drive}{partition_2} luksdev --key-file {pwfile} --type luks2'.format(**args))) - o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev')) # /dev/dm-0 - if b'cannot open' in o: + if not mount_luktsdev(args['drive'], args['partition_2'], args['pwfile']): print('[E] Could not open encrypted device.', o) exit(1) if not args['rerun'] or args['ignore-rerun']: print('[N] Creating btrfs filesystem inside {drive}{partition_2}'.format(**args)) - o = b''.join(sys_command('/usr/bin/mkfs.btrfs -f /dev/mapper/luksdev')) - if not b'UUID' in o: + if not mkfs_btrfs(): print('[E] Could not setup btrfs filesystem.', o) exit(1) - o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt') # /dev/dm-0 - if len(o) <= 0: - o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt')) - - os.makedirs('/mnt/boot', exist_ok=True) - o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot') # /dev/dm-0 - if len(o) <= 0: - o = b''.join(sys_command('/usr/bin/mount {drive}{partition_1} /mnt/boot'.format(**args))) + mount_mountpoints(args['drive'], args['partition_1']) if 'mirrors' in args and args['mirrors'] and 'country' in args and get_default_gateway_linux(): print('[N] Reordering mirrors.') -- cgit v1.2.3-70-g09d2 From 5a4e1ec0925528003d49c8ba97d214987e750674 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 20:46:46 +0000 Subject: Cleaned up the entire format process into functions. --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 2749458d..452f62f2 100644 --- a/archinstall.py +++ b/archinstall.py @@ -828,7 +828,7 @@ def mount_luksdev(where='/dev/mapper/luksdev', to='/mnt', *positionals, **kwargs o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt')) return True -def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs) +def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs): os.makedirs('/mnt/boot', exist_ok=True) o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot') # /dev/dm-0 if len(o) <= 0: -- cgit v1.2.3-70-g09d2 From f2e3d8ecf28e0e2d3398948d8b283974d7484ec2 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 21:17:16 +0000 Subject: Converted to a new mode. Each parameter to the functions, are given as strings and later mapped to the args[] structure. This so that you can supply keys in advanced without them being there. In order to chain functions together where functions some where along the chain supplies one of those values --- archinstall.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/archinstall.py b/archinstall.py index 452f62f2..415abc8e 100644 --- a/archinstall.py +++ b/archinstall.py @@ -587,7 +587,10 @@ def close_disks(): o = simple_command('/usr/bin/umount -R /mnt') o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') -def format_disk(drive=None, start='512MiB', end='100%', emulate=False, *args, **kwargs): +def format_disk(drive='drive', start='start', end='size', emulate=False, *args, **kwargs): + drive = args[drive] + start = args[start] + end = args[end] if not drive: raise ValueError('Need to supply a drive path, for instance: /dev/sdx') print(f'[N] Setting up {drive}.') @@ -790,10 +793,13 @@ def cache_diskpw_on_disk(): pw.write(args['password']) def refresh_partition_list(drive, *positionals, **kwargs): + drive = args[drive] args['paritions'] = get_partitions(drive, *positionals, **kwargs) return True def mkfs_fat32(drive, partition, *positionals, **kwargs): + drive = args[drive] + partition = args[partition] o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {drive}{partition}')) if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: return None @@ -806,11 +812,17 @@ def is_luksdev_mounted(*positionals, **kwargs): return True def mount_luktsdev(drive, partition, keyfile, *positionals, **kwargs): + drive = args[drive] + partition = args[partition] + keyfile = args[keyfile] if not is_luksdev_mounted(): o = b''.join(sys_command(f'/usr/bin/cryptsetup open {drive}{partition} luksdev --key-file {keyfile} --type luks2'.format(**args))) return is_luksdev_mounted() def encrypt_partition(drive, partition, keyfile='/tmp/diskpw', *positionals, **kwargs): + drive = args[drive] + partition = args[partition] + keyfile = args[keyfile] o = b''.join(sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {keyfile} --use-urandom luksFormat {drive}{partition}')) if not b'Command successful.' in o: return False @@ -836,6 +848,8 @@ def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs) return True def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot'): + drive = args[drive] + bootpartition = args[bootpartition] mount_luksdev() mount_boot(drive, bootpartition, mountpoint='/mnt/boot') @@ -895,9 +909,9 @@ if __name__ == '__main__': time.sleep(1) close_disks() - format_disk(args['drive'], start=args['start'], end=args['size']) + format_disk('drive', start='start', end='size') - refresh_partition_list(args['drive']) + refresh_partition_list('drive') print(f'Partitions: (Boot: {list(args["paritions"].keys())[0]})') if len(args['paritions']) <= 0: @@ -909,18 +923,18 @@ if __name__ == '__main__': print(json.dumps(args['paritions'][part_name], indent=4)) if not args['rerun'] or args['ignore-rerun']: - if not mkfs_fat32(args['drive'], args['partition_1'], *positionals, **kwargs): + if not mkfs_fat32('drive', 'partition_1', *positionals, **kwargs): print('[E] Could not setup {drive}{partition_1}'.format(**args)) exit(1) # "--cipher sha512" breaks the shit. # TODO: --use-random instead of --use-urandom print('[N] Adding encryption to {drive}{partition_2}.'.format(**args)) - if not encrypt_partition(args['drive'], args['partition_2'], args['pwfile']): + if not encrypt_partition('drive', 'partition_2', 'pwfile'): print('[E] Failed to setup disk encryption.', o) exit(1) - if not mount_luktsdev(args['drive'], args['partition_2'], args['pwfile']): + if not mount_luktsdev('drive', 'partition_2', 'pwfile'): print('[E] Could not open encrypted device.', o) exit(1) @@ -930,7 +944,7 @@ if __name__ == '__main__': print('[E] Could not setup btrfs filesystem.', o) exit(1) - mount_mountpoints(args['drive'], args['partition_1']) + mount_mountpoints('drive', 'partition_1') if 'mirrors' in args and args['mirrors'] and 'country' in args and get_default_gateway_linux(): print('[N] Reordering mirrors.') -- cgit v1.2.3-70-g09d2 From 3bcfd23b30509336ac5bdbd72cc7163d091edc3c Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 21:19:33 +0000 Subject: Positions, not args --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 415abc8e..59af0fee 100644 --- a/archinstall.py +++ b/archinstall.py @@ -587,7 +587,7 @@ def close_disks(): o = simple_command('/usr/bin/umount -R /mnt') o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') -def format_disk(drive='drive', start='start', end='size', emulate=False, *args, **kwargs): +def format_disk(drive='drive', start='start', end='size', emulate=False, *positionals, **kwargs): drive = args[drive] start = args[start] end = args[end] -- cgit v1.2.3-70-g09d2 From 9e322c0205f2d1de75cc6336011dcb4ddd72238b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 21:36:12 +0000 Subject: Fetching partitions from the partition tree in the dictionary. --- archinstall.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/archinstall.py b/archinstall.py index 59af0fee..0380bb22 100644 --- a/archinstall.py +++ b/archinstall.py @@ -799,7 +799,7 @@ def refresh_partition_list(drive, *positionals, **kwargs): def mkfs_fat32(drive, partition, *positionals, **kwargs): drive = args[drive] - partition = args[partition] + partition = args['paritions'][partition] o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {drive}{partition}')) if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: return None @@ -813,7 +813,7 @@ def is_luksdev_mounted(*positionals, **kwargs): def mount_luktsdev(drive, partition, keyfile, *positionals, **kwargs): drive = args[drive] - partition = args[partition] + partition = args['paritions'][partition] keyfile = args[keyfile] if not is_luksdev_mounted(): o = b''.join(sys_command(f'/usr/bin/cryptsetup open {drive}{partition} luksdev --key-file {keyfile} --type luks2'.format(**args))) @@ -821,7 +821,7 @@ def mount_luktsdev(drive, partition, keyfile, *positionals, **kwargs): def encrypt_partition(drive, partition, keyfile='/tmp/diskpw', *positionals, **kwargs): drive = args[drive] - partition = args[partition] + partition = args['paritions'][partition] keyfile = args[keyfile] o = b''.join(sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {keyfile} --use-urandom luksFormat {drive}{partition}')) if not b'Command successful.' in o: -- cgit v1.2.3-70-g09d2 From 4cd31af1b0e4409d96f3d9c4107d58d68b9924a9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 21:37:34 +0000 Subject: Debugging --- archinstall.py | 1 + 1 file changed, 1 insertion(+) diff --git a/archinstall.py b/archinstall.py index 0380bb22..a9295f22 100644 --- a/archinstall.py +++ b/archinstall.py @@ -795,6 +795,7 @@ def cache_diskpw_on_disk(): def refresh_partition_list(drive, *positionals, **kwargs): drive = args[drive] args['paritions'] = get_partitions(drive, *positionals, **kwargs) + print(json.dumps(args['paritions'], indent=4)) return True def mkfs_fat32(drive, partition, *positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 0afa90f815c78d2c45bdd3fecfc5e4f801269eed Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 21:46:07 +0000 Subject: Refresh partitions function enhanced. Previously it just returned a unsorted mess, now the args['partitions'] structure is finalized in that function --- archinstall.py | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/archinstall.py b/archinstall.py index a9295f22..a0f69c07 100644 --- a/archinstall.py +++ b/archinstall.py @@ -399,7 +399,7 @@ def get_drive_from_part_uuid(partuuid, *positionals, **kwargs): for drive in harddrives: for partition in get_partitions(f'/dev/{drive}', *positionals, **kwargs): - o = simple_command(f'blkid -s PARTUUID -o value /dev/{drive}') + o = simple_command(f'blkid -s PARTUUID -o value /dev/{drive}{partition}') if len(o) and o == partuuid: return drive @@ -794,8 +794,9 @@ def cache_diskpw_on_disk(): def refresh_partition_list(drive, *positionals, **kwargs): drive = args[drive] - args['paritions'] = get_partitions(drive, *positionals, **kwargs) - print(json.dumps(args['paritions'], indent=4)) + partitions = oDict() + for index, part_name in enumerate(sorted(get_partitions(drive, *positionals, **kwargs).keys())): + args['partitions'][index+1] = part_name return True def mkfs_fat32(drive, partition, *positionals, **kwargs): @@ -918,34 +919,30 @@ if __name__ == '__main__': if len(args['paritions']) <= 0: print('[E] No paritions were created on {drive}'.format(**args), o) exit(1) - for index, part_name in enumerate(sorted(args['paritions'].keys())): - args['partition_{}'.format(index+1)] = part_name - print(f'Partition info: {part_name}') - print(json.dumps(args['paritions'][part_name], indent=4)) if not args['rerun'] or args['ignore-rerun']: - if not mkfs_fat32('drive', 'partition_1', *positionals, **kwargs): - print('[E] Could not setup {drive}{partition_1}'.format(**args)) + if not mkfs_fat32('drive', '1', *positionals, **kwargs): + print(f'[E] Could not setup {args["drive"]}{args["paritions"]["1"]}') exit(1) # "--cipher sha512" breaks the shit. # TODO: --use-random instead of --use-urandom - print('[N] Adding encryption to {drive}{partition_2}.'.format(**args)) - if not encrypt_partition('drive', 'partition_2', 'pwfile'): + print(f'[N] Adding encryption to {drive}{partitions["2"]}.') + if not encrypt_partition('drive', '2', 'pwfile'): print('[E] Failed to setup disk encryption.', o) exit(1) - if not mount_luktsdev('drive', 'partition_2', 'pwfile'): + if not mount_luktsdev('drive', '2', 'pwfile'): print('[E] Could not open encrypted device.', o) exit(1) if not args['rerun'] or args['ignore-rerun']: - print('[N] Creating btrfs filesystem inside {drive}{partition_2}'.format(**args)) + print(f'[N] Creating btrfs filesystem inside {args["drive"]}{args["partitions"]["2"]}') if not mkfs_btrfs(): print('[E] Could not setup btrfs filesystem.', o) exit(1) - mount_mountpoints('drive', 'partition_1') + mount_mountpoints('drive', '1') if 'mirrors' in args and args['mirrors'] and 'country' in args and get_default_gateway_linux(): print('[N] Reordering mirrors.') @@ -1042,7 +1039,7 @@ if __name__ == '__main__': ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. ## And blkid is wrong in terms of LUKS. #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() - UUID = simple_command("ls -l /dev/disk/by-uuid/ | grep {basename}{partition_2} | awk '{{print $9}}'".format(basename=os.path.basename(args['drive']), **args)).decode('UTF-8').strip() + UUID = simple_command(f"ls -l /dev/disk/by-uuid/ | grep {os.path.basename(args['drive'])}{args['partitions']['2']} | awk '{{print $9}}'").decode('UTF-8').strip() with open('/mnt/boot/loader/entries/arch.conf', 'w') as entry: entry.write('title Arch Linux\n') entry.write('linux /vmlinuz-linux\n') -- cgit v1.2.3-70-g09d2 From 3c2a88bd7a8f0face88628f09b90bad61c185ed9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 21:47:49 +0000 Subject: Refresh partitions function enhanced. Previously it just returned a unsorted mess, now the args['partitions'] structure is finalized in that function --- archinstall.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/archinstall.py b/archinstall.py index a0f69c07..297eb12a 100644 --- a/archinstall.py +++ b/archinstall.py @@ -611,7 +611,7 @@ def format_disk(drive='drive', start='start', end='size', emulate=False, *positi if sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {end}', emulate=emulate).exit_code != 0: return None - # TODO: grab paritions after each parted/partition step instead of guessing which partiton is which later on. + # TODO: grab partitions after each parted/partition step instead of guessing which partiton is which later on. # Create one, grab partitions - dub that to "boot" or something. do the next partition, grab that and dub it "system".. or something.. # This "assumption" has bit me in the ass so many times now I've stoped counting.. Jerker is right.. Don't do it like this :P @@ -794,14 +794,15 @@ def cache_diskpw_on_disk(): def refresh_partition_list(drive, *positionals, **kwargs): drive = args[drive] - partitions = oDict() + if not 'partitions' in args: + args['partitions'] = oDict() for index, part_name in enumerate(sorted(get_partitions(drive, *positionals, **kwargs).keys())): args['partitions'][index+1] = part_name return True def mkfs_fat32(drive, partition, *positionals, **kwargs): drive = args[drive] - partition = args['paritions'][partition] + partition = args['partitions'][partition] o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {drive}{partition}')) if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: return None @@ -815,7 +816,7 @@ def is_luksdev_mounted(*positionals, **kwargs): def mount_luktsdev(drive, partition, keyfile, *positionals, **kwargs): drive = args[drive] - partition = args['paritions'][partition] + partition = args['partitions'][partition] keyfile = args[keyfile] if not is_luksdev_mounted(): o = b''.join(sys_command(f'/usr/bin/cryptsetup open {drive}{partition} luksdev --key-file {keyfile} --type luks2'.format(**args))) @@ -823,7 +824,7 @@ def mount_luktsdev(drive, partition, keyfile, *positionals, **kwargs): def encrypt_partition(drive, partition, keyfile='/tmp/diskpw', *positionals, **kwargs): drive = args[drive] - partition = args['paritions'][partition] + partition = args['partitions'][partition] keyfile = args[keyfile] o = b''.join(sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash sha512 --key-size 512 --iter-time 10000 --key-file {keyfile} --use-urandom luksFormat {drive}{partition}')) if not b'Command successful.' in o: @@ -914,15 +915,15 @@ if __name__ == '__main__': format_disk('drive', start='start', end='size') refresh_partition_list('drive') - print(f'Partitions: (Boot: {list(args["paritions"].keys())[0]})') + print(f'Partitions: (Boot: {list(args["partitions"].keys())[0]})') - if len(args['paritions']) <= 0: - print('[E] No paritions were created on {drive}'.format(**args), o) + if len(args['partitions']) <= 0: + print('[E] No partitions were created on {drive}'.format(**args), o) exit(1) if not args['rerun'] or args['ignore-rerun']: if not mkfs_fat32('drive', '1', *positionals, **kwargs): - print(f'[E] Could not setup {args["drive"]}{args["paritions"]["1"]}') + print(f'[E] Could not setup {args["drive"]}{args["partitions"]["1"]}') exit(1) # "--cipher sha512" breaks the shit. -- cgit v1.2.3-70-g09d2 From 3657cc5c6e2315f62273272c297f769e472a6fd5 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 21:50:56 +0000 Subject: Debugging --- archinstall.py | 1 + 1 file changed, 1 insertion(+) diff --git a/archinstall.py b/archinstall.py index 297eb12a..525387f9 100644 --- a/archinstall.py +++ b/archinstall.py @@ -801,6 +801,7 @@ def refresh_partition_list(drive, *positionals, **kwargs): return True def mkfs_fat32(drive, partition, *positionals, **kwargs): + print(json.dumps(args, indent=4)) drive = args[drive] partition = args['partitions'][partition] o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {drive}{partition}')) -- cgit v1.2.3-70-g09d2 From 1129dae13d0f5cb9c33acd8b46b3173cb1a2e86a Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 22:02:45 +0000 Subject: Debugging --- archinstall.py | 1 + 1 file changed, 1 insertion(+) diff --git a/archinstall.py b/archinstall.py index 525387f9..0a82ace7 100644 --- a/archinstall.py +++ b/archinstall.py @@ -803,6 +803,7 @@ def refresh_partition_list(drive, *positionals, **kwargs): def mkfs_fat32(drive, partition, *positionals, **kwargs): print(json.dumps(args, indent=4)) drive = args[drive] + print(partition, type(partition), args['partitions'], type(args['partitions'])) partition = args['partitions'][partition] o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {drive}{partition}')) if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: -- cgit v1.2.3-70-g09d2 From 29b091e0370bdde3a6955b8b646174436fad18b8 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 22:03:49 +0000 Subject: String convertion on part numbers, maybe a stupid idea? --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 0a82ace7..f2ed3a7a 100644 --- a/archinstall.py +++ b/archinstall.py @@ -797,7 +797,7 @@ def refresh_partition_list(drive, *positionals, **kwargs): if not 'partitions' in args: args['partitions'] = oDict() for index, part_name in enumerate(sorted(get_partitions(drive, *positionals, **kwargs).keys())): - args['partitions'][index+1] = part_name + args['partitions'][str(index+1)] = part_name return True def mkfs_fat32(drive, partition, *positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 755efe5706590dd096be551847855293c641df89 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 22:05:17 +0000 Subject: Positions and kwargs not added to functions --- archinstall.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/archinstall.py b/archinstall.py index f2ed3a7a..00744044 100644 --- a/archinstall.py +++ b/archinstall.py @@ -801,9 +801,7 @@ def refresh_partition_list(drive, *positionals, **kwargs): return True def mkfs_fat32(drive, partition, *positionals, **kwargs): - print(json.dumps(args, indent=4)) drive = args[drive] - print(partition, type(partition), args['partitions'], type(args['partitions'])) partition = args['partitions'][partition] o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {drive}{partition}')) if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: @@ -852,11 +850,11 @@ def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs) o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}')) return True -def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot'): +def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs): drive = args[drive] bootpartition = args[bootpartition] - mount_luksdev() - mount_boot(drive, bootpartition, mountpoint='/mnt/boot') + mount_luksdev(*positionals, **kwargs) + mount_boot(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs) if __name__ == '__main__': update_git() # Breaks and restarts the script if an update was found. -- cgit v1.2.3-70-g09d2 From ceb73c5523d5ff8fb32e8a95d16d0d81914fbcfc Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 22:09:24 +0000 Subject: Correction on args fetching --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 00744044..76afbddc 100644 --- a/archinstall.py +++ b/archinstall.py @@ -852,7 +852,7 @@ def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs) def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs): drive = args[drive] - bootpartition = args[bootpartition] + bootpartition = args['partitions'][bootpartition] mount_luksdev(*positionals, **kwargs) mount_boot(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs) -- cgit v1.2.3-70-g09d2 From fda94e5b9579298478c79d53c08e9f80ea4424ed Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 22:14:54 +0000 Subject: Forgot return value --- archinstall.py | 1 + 1 file changed, 1 insertion(+) diff --git a/archinstall.py b/archinstall.py index 76afbddc..7067d5ec 100644 --- a/archinstall.py +++ b/archinstall.py @@ -855,6 +855,7 @@ def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals bootpartition = args['partitions'][bootpartition] mount_luksdev(*positionals, **kwargs) mount_boot(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs) + return True if __name__ == '__main__': update_git() # Breaks and restarts the script if an update was found. -- cgit v1.2.3-70-g09d2 From cf865c98b59562f6cf8e1761b0a925aa1c01ab1f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 23:12:36 +0000 Subject: Finished moving almost all steps into functions. --- archinstall.py | 337 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 184 insertions(+), 153 deletions(-) diff --git a/archinstall.py b/archinstall.py index 7067d5ec..d0bd23b8 100644 --- a/archinstall.py +++ b/archinstall.py @@ -502,7 +502,7 @@ def disk_info(drive, *positionals, **kwargs): lkwargs = {**kwargs} lkwargs['emulate'] = False # This is a emulate-safe function. Does not alter filesystem. - info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}', *positionals, **lkwargs)).decode('UTF_8'))['blockdevices'][0] + info = json.loads(b''.join(sys_command(f'lsblk -J -o "NAME,SIZE,FSTYPE,LABEL" {drive}', *positionals, **lkwargs, hide_from_log=True)).decode('UTF_8'))['blockdevices'][0] fileformats = [] labels = [] if 'children' in info: ## Might not be partitioned yet @@ -809,7 +809,7 @@ def mkfs_fat32(drive, partition, *positionals, **kwargs): return True def is_luksdev_mounted(*positionals, **kwargs): - o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev')) # /dev/dm-0 + o = b''.join(sys_command('/usr/bin/file /dev/mapper/luksdev', hide_from_log=True)) # /dev/dm-0 if b'cannot open' in o: return False return True @@ -857,6 +857,182 @@ def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals mount_boot(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs) return True +def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): + ## TODO: replace wget with urllib.request (no point in calling syscommand) + country_list = [] + for country in countries.split(','): + country_list.append(f'country={country}') + o = simple_command(f"/usr/bin/wget 'https://www.archlinux.org/mirrorlist/?{'&'.join(country_list)}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist") + o = simple_command("/usr/bin/sed -i 's/#Server/Server/' /root/mirrorlist") + o = simple_command('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist') + return True + +def strap_in_base(*positionals, **kwargs): + if args['aur-support']: + args['packages'] += ' git' + if sys_command('/usr/bin/pacman -Syy').exit_code == 0: + if sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args)).exit_code == 0: + return True + return False + +def configure_base_system(*positionals, **kwargs): + ## TODO: Replace a lot of these syscalls with just python native operations. + o = b''.join(sys_command('/usr/bin/genfstab -pU /mnt >> /mnt/etc/fstab')) + with open('/mnt/etc/fstab', 'a') as fstab: + fstab.write('\ntmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0\n') # Redundant \n at the start? who knoes? + + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt rm -f /etc/localtime')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt ln -s /usr/share/zoneinfo/{localtime} /etc/localtime'.format(**args))) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime')) + #o = sys_command('arch-chroot /mnt echo "{hostname}" > /etc/hostname'.format(**args)) + #o = sys_command("arch-chroot /mnt sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen") + o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo '{hostname}' > /etc/hostname\"".format(**args))) + o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen\"")) + o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'LANG=en_US.UTF-8' > /etc/locale.conf\"")) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt locale-gen')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt chmod 700 /root')) + + with open('/mnt/etc/mkinitcpio.conf', 'w') as mkinit: + ## TODO: Don't replace it, in case some update in the future actually adds something. + 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 keyboard fsck)\n') + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt mkinitcpio -p linux')) + + return True + +def setup_bootloader(*positionals, **kwargs): + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt bootctl --no-variables --path=/boot install')) + + with open('/mnt/boot/loader/loader.conf', 'w') as loader: + loader.write('default arch\n') + loader.write('timeout 5\n') + + ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. + ## And blkid is wrong in terms of LUKS. + #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() + UUID = simple_command(f"ls -l /dev/disk/by-uuid/ | grep {os.path.basename(args['drive'])}{args['partitions']['2']} | awk '{{print $9}}'").decode('UTF-8').strip() + with open('/mnt/boot/loader/entries/arch.conf', 'w') as entry: + entry.write('title Arch Linux\n') + entry.write('linux /vmlinuz-linux\n') + entry.write('initrd /initramfs-linux.img\n') + entry.write('options cryptdevice=UUID={UUID}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n'.format(UUID=UUID)) + + return True + +def add_AUR_support(*positionals, **kwargs): + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "useradd -m -G wheel aibuilder"')) + o = b''.join(sys_command("/usr/bin/sed -i 's/# %wheel ALL=(ALL) NO/%wheel ALL=(ALL) NO/' /mnt/etc/sudoers")) + + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder; git clone https://aur.archlinux.org/yay.git)\\""')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "chown -R aibuilder.aibuilder /home/aibuilder/yay"')) + o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder/yay; makepkg -si --noconfirm)\\" >/dev/null"')) + ## Do not remove aibuilder just yet, can be used later for aur packages. + #o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers')) + #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"')) + #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"')) + return True + +def run_post_install_steps(*positionals, **kwargs): + conf = {} + if 'post' in instructions: + conf = instructions['post'] + elif not 'args' in instructions and len(instructions): + conf = instructions + + if 'git-branch' in conf: + update_git(conf['git-branch']) + del(conf['git-branch']) + + for title in conf: + if args['rerun'] and args['rerun'] != title and not rerun: + continue + else: + rerun = True + + print('[N] Network Deploy: {}'.format(title)) + if type(conf[title]) == str: + print('[N] Loading {} configuration'.format(conf[title])) + conf[title] = get_application_instructions(conf[title]) + + for command in conf[title]: + raw_command = command + opts = conf[title][command] if type(conf[title][command]) in (dict, oDict) else {} + if len(opts): + if 'pass-args' in opts or 'format' in opts: + command = command.format(**args) + ## FIXME: Instead of deleting the two options + ## in order to mute command output further down, + ## check for a 'debug' flag per command and delete these two + if 'pass-args' in opts: + del(opts['pass-args']) + elif 'format' in opts: + del(opts['format']) + elif ('debug' in opts and opts['debug']) or ('debug' in conf and conf['debug']): + print('[-] Options: {}'.format(opts)) + if 'pass-args' in opts and opts['pass-args']: + command = command.format(**args) + + if 'runas' in opts and f'su - {opts["runas"]} -c' not in command: + command = command.replace('"', '\\"') + command = f'su - {opts["runas"]} -c "{command}"' + + #print('[N] Command: {} ({})'.format(command, opts)) + + ## https://superuser.com/questions/1242978/start-systemd-nspawn-and-execute-commands-inside + ## !IMPORTANT + ## + ## arch-chroot mounts /run into the chroot environment, this breaks name resolves for some reason. + ## Either skipping mounting /run and using traditional chroot is an option, but using + ## `systemd-nspawn -D /mnt --machine temporary` might be a more flexible solution in case of file structure changes. + if 'no-chroot' in opts and opts['no-chroot']: + o = simple_command(command, opts) + elif 'chroot' in opts and opts['chroot']: + ## Run in a manually set up version of arch-chroot (arch-chroot will break namespaces). + ## This is a bit risky in case the file systems changes over the years, but we'll probably be safe adding this as an option. + ## **> Prefer if possible to use 'no-chroot' instead which "live boots" the OS and runs the command. + o = simple_command("mount /dev/mapper/luksdev /mnt") + o = simple_command("cd /mnt; cp /etc/resolv.conf etc") + o = simple_command("cd /mnt; mount -t proc /proc proc") + o = simple_command("cd /mnt; mount --make-rslave --rbind /sys sys") + o = simple_command("cd /mnt; mount --make-rslave --rbind /dev dev") + o = simple_command('chroot /mnt /bin/bash -c "{c}"'.format(c=command), opts=opts) + o = simple_command("cd /mnt; umount -R dev") + o = simple_command("cd /mnt; umount -R sys") + o = simple_command("cd /mnt; umount -R proc") + else: + if 'boot' in opts and opts['boot']: + ## So, if we're going to boot this maddafakker up, we'll need to + ## be able to login. The quickest way is to just add automatic login.. so lessgo! + + ## Turns out.. that didn't work exactly as planned.. + ## + # if not os.path.isdir('/mnt/etc/systemd/system/console-getty.service.d/'): + # os.makedirs('/mnt/etc/systemd/system/console-getty.service.d/') + # with open('/mnt/etc/systemd/system/console-getty.service.d/override.conf', 'w') as fh: + # fh.write('[Service]\n') + # fh.write('ExecStart=\n') + # fh.write('ExecStart=-/usr/bin/agetty --autologin root -s %I 115200,38400,9600 vt102\n') + + ## So we'll add a bunch of triggers instead and let the sys_command manually react to them. + ## " login" followed by "Passwodd" in case it's been set in a previous step.. usually this shouldn't be nessecary + ## since we set the password as the last step. And then the command itself which will be executed by looking for: + ## [root@ ~]# + o = b''.join(sys_command('/usr/bin/systemd-nspawn -D /mnt -b --machine temporary', opts={'triggers' : { + bytes(f'login:', 'UTF-8') : b'root\n', + #b'Password:' : bytes(args['password']+'\n', 'UTF-8'), + bytes(f'[root@{args["hostname"]} ~]#', 'UTF-8') : bytes(command+'\n', 'UTF-8'), + }, **opts})) + + ## Not needed anymore: And cleanup after out selves.. Don't want to leave any residue.. + # os.remove('/mnt/etc/systemd/system/console-getty.service.d/override.conf') + else: + o = b''.join(sys_command('/usr/bin/systemd-nspawn -D /mnt --machine temporary {c}'.format(c=command), opts=opts)) + if type(conf[title][raw_command]) == bytes and len(conf[title][raw_command]) and not conf[title][raw_command] in o: + print('[W] Post install command failed: {}'.format(o.decode('UTF-8'))) + #print(o) + if __name__ == '__main__': update_git() # Breaks and restarts the script if an update was found. update_drive_list() @@ -948,9 +1124,7 @@ if __name__ == '__main__': if 'mirrors' in args and args['mirrors'] and 'country' in args and get_default_gateway_linux(): print('[N] Reordering mirrors.') - o = simple_command("/usr/bin/wget 'https://www.archlinux.org/mirrorlist/?country={country}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist".format(**args)) - o = simple_command("/usr/bin/sed -i 's/#Server/Server/' /root/mirrorlist") - o = simple_command('/usr/bin/rankmirrors -n 6 /root/mirrorlist > /etc/pacman.d/mirrorlist') + filter_mirrors_by_country(args['country']) pre_conf = {} if 'pre' in instructions: @@ -999,166 +1173,23 @@ if __name__ == '__main__': if not args['rerun'] or rerun: print('[N] Straping in packages.') - if args['aur-support']: - args['packages'] += ' git' - o = b''.join(sys_command('/usr/bin/pacman -Syy')) - o = b''.join(sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args))) + strap_in_base() # TODO: check return here? we return based off pacstrap exit code.. Never tired it tho. if not os.path.isdir('/mnt/etc'): # TODO: This might not be the most long term stable thing to rely on... print('[E] Failed to strap in packages', o) exit(1) if not args['rerun'] or rerun: - o = b''.join(sys_command('/usr/bin/genfstab -pU /mnt >> /mnt/etc/fstab')) - with open('/mnt/etc/fstab', 'a') as fstab: - fstab.write('\ntmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0\n') # Redundant \n at the start? who knoes? - - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt rm -f /etc/localtime')) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt ln -s /usr/share/zoneinfo/{localtime} /etc/localtime'.format(**args))) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime')) - #o = sys_command('arch-chroot /mnt echo "{hostname}" > /etc/hostname'.format(**args)) - #o = sys_command("arch-chroot /mnt sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen") - o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo '{hostname}' > /etc/hostname\"".format(**args))) - o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen\"")) - o = b''.join(sys_command("/usr/bin/arch-chroot /mnt sh -c \"echo 'LANG=en_US.UTF-8' > /etc/locale.conf\"")) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt locale-gen')) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt chmod 700 /root')) - - with open('/mnt/etc/mkinitcpio.conf', 'w') as mkinit: - ## TODO: Don't replace it, in case some update in the future actually adds something. - 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 keyboard fsck)\n') - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt mkinitcpio -p linux')) + configure_base_system() ## WORKAROUND: https://github.com/systemd/systemd/issues/13603#issuecomment-552246188 - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt bootctl --no-variables --path=/boot install')) - - with open('/mnt/boot/loader/loader.conf', 'w') as loader: - loader.write('default arch\n') - loader.write('timeout 5\n') - - ## For some reason, blkid and /dev/disk/by-uuid are not getting along well. - ## And blkid is wrong in terms of LUKS. - #UUID = sys_command('blkid -s PARTUUID -o value {drive}{partition_2}'.format(**args)).decode('UTF-8').strip() - UUID = simple_command(f"ls -l /dev/disk/by-uuid/ | grep {os.path.basename(args['drive'])}{args['partitions']['2']} | awk '{{print $9}}'").decode('UTF-8').strip() - with open('/mnt/boot/loader/entries/arch.conf', 'w') as entry: - entry.write('title Arch Linux\n') - entry.write('linux /vmlinuz-linux\n') - entry.write('initrd /initramfs-linux.img\n') - entry.write('options cryptdevice=UUID={UUID}:luksdev root=/dev/mapper/luksdev rw intel_pstate=no_hwp\n'.format(UUID=UUID)) + setup_bootloader() if args['aur-support']: print('[N] AUR support demanded, building "yay" before running POST steps.') - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "useradd -m -G wheel aibuilder"')) - o = b''.join(sys_command("/usr/bin/sed -i 's/# %wheel ALL=(ALL) NO/%wheel ALL=(ALL) NO/' /mnt/etc/sudoers")) - - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder; git clone https://aur.archlinux.org/yay.git)\\""')) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "chown -R aibuilder.aibuilder /home/aibuilder/yay"')) - o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "su - aibuilder -c \\"(cd /home/aibuilder/yay; makepkg -si --noconfirm)\\" >/dev/null"')) - ## Do not remove aibuilder just yet, can be used later for aur packages. - #o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers')) - #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"')) - #o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"')) + add_AUR_support() print('[N] AUR support added. use "yay -Syy --noconfirm " to deploy in POST.') - conf = {} - if 'post' in instructions: - conf = instructions['post'] - elif not 'args' in instructions and len(instructions): - conf = instructions - - if 'git-branch' in conf: - update_git(conf['git-branch']) - del(conf['git-branch']) - - for title in conf: - if args['rerun'] and args['rerun'] != title and not rerun: - continue - else: - rerun = True - - print('[N] Network Deploy: {}'.format(title)) - if type(conf[title]) == str: - print('[N] Loading {} configuration'.format(conf[title])) - conf[title] = get_application_instructions(conf[title]) - - for command in conf[title]: - raw_command = command - opts = conf[title][command] if type(conf[title][command]) in (dict, oDict) else {} - if len(opts): - if 'pass-args' in opts or 'format' in opts: - command = command.format(**args) - ## FIXME: Instead of deleting the two options - ## in order to mute command output further down, - ## check for a 'debug' flag per command and delete these two - if 'pass-args' in opts: - del(opts['pass-args']) - elif 'format' in opts: - del(opts['format']) - elif ('debug' in opts and opts['debug']) or ('debug' in conf and conf['debug']): - print('[-] Options: {}'.format(opts)) - if 'pass-args' in opts and opts['pass-args']: - command = command.format(**args) - - if 'runas' in opts and f'su - {opts["runas"]} -c' not in command: - command = command.replace('"', '\\"') - command = f'su - {opts["runas"]} -c "{command}"' - - #print('[N] Command: {} ({})'.format(command, opts)) - - ## https://superuser.com/questions/1242978/start-systemd-nspawn-and-execute-commands-inside - ## !IMPORTANT - ## - ## arch-chroot mounts /run into the chroot environment, this breaks name resolves for some reason. - ## Either skipping mounting /run and using traditional chroot is an option, but using - ## `systemd-nspawn -D /mnt --machine temporary` might be a more flexible solution in case of file structure changes. - if 'no-chroot' in opts and opts['no-chroot']: - o = simple_command(command, opts) - elif 'chroot' in opts and opts['chroot']: - ## Run in a manually set up version of arch-chroot (arch-chroot will break namespaces). - ## This is a bit risky in case the file systems changes over the years, but we'll probably be safe adding this as an option. - ## **> Prefer if possible to use 'no-chroot' instead which "live boots" the OS and runs the command. - o = simple_command("mount /dev/mapper/luksdev /mnt") - o = simple_command("cd /mnt; cp /etc/resolv.conf etc") - o = simple_command("cd /mnt; mount -t proc /proc proc") - o = simple_command("cd /mnt; mount --make-rslave --rbind /sys sys") - o = simple_command("cd /mnt; mount --make-rslave --rbind /dev dev") - o = simple_command('chroot /mnt /bin/bash -c "{c}"'.format(c=command), opts=opts) - o = simple_command("cd /mnt; umount -R dev") - o = simple_command("cd /mnt; umount -R sys") - o = simple_command("cd /mnt; umount -R proc") - else: - if 'boot' in opts and opts['boot']: - ## So, if we're going to boot this maddafakker up, we'll need to - ## be able to login. The quickest way is to just add automatic login.. so lessgo! - - ## Turns out.. that didn't work exactly as planned.. - ## - # if not os.path.isdir('/mnt/etc/systemd/system/console-getty.service.d/'): - # os.makedirs('/mnt/etc/systemd/system/console-getty.service.d/') - # with open('/mnt/etc/systemd/system/console-getty.service.d/override.conf', 'w') as fh: - # fh.write('[Service]\n') - # fh.write('ExecStart=\n') - # fh.write('ExecStart=-/usr/bin/agetty --autologin root -s %I 115200,38400,9600 vt102\n') - - ## So we'll add a bunch of triggers instead and let the sys_command manually react to them. - ## " login" followed by "Passwodd" in case it's been set in a previous step.. usually this shouldn't be nessecary - ## since we set the password as the last step. And then the command itself which will be executed by looking for: - ## [root@ ~]# - o = b''.join(sys_command('/usr/bin/systemd-nspawn -D /mnt -b --machine temporary', opts={'triggers' : { - bytes(f'login:', 'UTF-8') : b'root\n', - #b'Password:' : bytes(args['password']+'\n', 'UTF-8'), - bytes(f'[root@{args["hostname"]} ~]#', 'UTF-8') : bytes(command+'\n', 'UTF-8'), - }, **opts})) - - ## Not needed anymore: And cleanup after out selves.. Don't want to leave any residue.. - # os.remove('/mnt/etc/systemd/system/console-getty.service.d/override.conf') - else: - o = b''.join(sys_command('/usr/bin/systemd-nspawn -D /mnt --machine temporary {c}'.format(c=command), opts=opts)) - if type(conf[title][raw_command]) == bytes and len(conf[title][raw_command]) and not conf[title][raw_command] in o: - print('[W] Post install command failed: {}'.format(o.decode('UTF-8'))) - #print(o) + run_post_install_steps() if args['aur-support']: o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers')) -- cgit v1.2.3-70-g09d2 From 03ceef69f17897b0f725bb29ce1ac3206d7e4c8e Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 23:35:09 +0000 Subject: Debugging --- archinstall.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index d0bd23b8..41e67c3a 100644 --- a/archinstall.py +++ b/archinstall.py @@ -870,8 +870,8 @@ def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): def strap_in_base(*positionals, **kwargs): if args['aur-support']: args['packages'] += ' git' - if sys_command('/usr/bin/pacman -Syy').exit_code == 0: - if sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args)).exit_code == 0: + if sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs).exit_code == 0: + if sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args), *positionals, **kwargs).exit_code == 0: return True return False -- cgit v1.2.3-70-g09d2 From 4f394d40ceddb5d9c9de7a11b2dc1efeaf2ad19f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 23:42:04 +0000 Subject: mismatch between archinstall and archinstall_gui in the worker class --- archinstall.py | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/archinstall.py b/archinstall.py index 41e67c3a..9cf7246a 100644 --- a/archinstall.py +++ b/archinstall.py @@ -370,17 +370,38 @@ class sys_command():#Thread): worker_history[self.worker_id] = self.dump() - if 'dependency' in self.kwargs and self.exit_code == 0: - ## If this had a dependency waiting, - ## Start it since there's no hook for this yet, the worker has to spawn it's waiting workers. - module = self.kwargs['dependency']['module'] - print(self.cmd[0],'fullfills a dependency:', module) - dependency_id = self.kwargs['dependency']['id'] - dependencies[module][dependency_id]['fullfilled'] = True - dependencies[module][dependency_id]['spawn'](*dependencies[module][dependency_id]['args'], **dependencies[module][dependency_id]['kwargs'], start_callback=_worker_started_notification) + if 'dependency' in self.kwargs: + pass # TODO: Not yet supported (steal it from archinstall_gui) + """ + dependency = self.kwargs['dependency'] + if type(dependency) == str: + # Dependency is a progress-string. Wait for it to show up. + while main and main.isAlive() and dependency not in progress or progress[dependency] is None: + time.sleep(0.25) + dependency = progress[dependency] + + if type(dependency) == str: + log(f"{self.func} waited for progress {dependency} which never showed up. Aborting.", level=2, origin='worker', function='run') + self.ended = time.time() + self.status = 'aborted' + return None + + while main and main.isAlive() and dependency.ended is None: + time.sleep(0.25) + + print(' *** Dependency released for:', self.func) + + if dependency.data is None or not main or not main.isAlive(): + log('Dependency:', dependency.func, 'did not exit clearly. There for,', self.func, 'can not execute.', level=2, origin='worker', function='run') + self.ended = time.time() + self.status = 'aborted' + return None + """ if self.callback: - self.callback(self, *self.args, **self.kwargs) + pass # TODO: Not yet supported (steal it from archinstall_gui) + + #self.callback(self, *self.args, **self.kwargs) def get_drive_from_uuid(uuid): if len(harddrives) <= 0: raise ValueError("No hard drives to iterate in order to find: {}".format(uuid)) -- cgit v1.2.3-70-g09d2 From d80d74b82090a9097bc483f81ae5d84643007ca3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 18 Nov 2019 23:44:50 +0000 Subject: Debugging --- archinstall.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index 9cf7246a..2e1a9b7a 100644 --- a/archinstall.py +++ b/archinstall.py @@ -257,7 +257,7 @@ class sys_command():#Thread): yield line def __repr__(self, *positionals, **kwargs): - return self.trace_log.decode('UTF-8') + return f"{self.cmd, self.trace_log}" def decode(self, fmt='UTF-8'): return self.trace_log.decode(fmt) @@ -891,7 +891,10 @@ def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): def strap_in_base(*positionals, **kwargs): if args['aur-support']: args['packages'] += ' git' - if sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs).exit_code == 0: + x = sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs) + print(x) + print(x.exit_code) + if x.exit_code == 0: if sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args), *positionals, **kwargs).exit_code == 0: return True return False -- cgit v1.2.3-70-g09d2 From e7e7390c7e0325cc0b214e04126d853ca4f770f3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:07:33 +0000 Subject: Debug --- archinstall.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index 2e1a9b7a..67a64cd7 100644 --- a/archinstall.py +++ b/archinstall.py @@ -892,8 +892,8 @@ def strap_in_base(*positionals, **kwargs): if args['aur-support']: args['packages'] += ' git' x = sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs) - print(x) - print(x.exit_code) + print('Handle:', x) + print('Exit code:', x.exit_code) if x.exit_code == 0: if sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args), *positionals, **kwargs).exit_code == 0: return True -- cgit v1.2.3-70-g09d2 From 22698ad65cbd5c24870f0e03eb8b5986ea3f7b88 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:09:25 +0000 Subject: debugging --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 67a64cd7..d62949ba 100644 --- a/archinstall.py +++ b/archinstall.py @@ -893,7 +893,7 @@ def strap_in_base(*positionals, **kwargs): args['packages'] += ' git' x = sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs) print('Handle:', x) - print('Exit code:', x.exit_code) + print('Exit code:', x.exit_code, x.exit_code == 0) if x.exit_code == 0: if sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args), *positionals, **kwargs).exit_code == 0: return True -- cgit v1.2.3-70-g09d2 From 42676d57877bcccb8e5f2869891a790e94d450a0 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:11:43 +0000 Subject: debugging --- archinstall.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/archinstall.py b/archinstall.py index d62949ba..26091ea8 100644 --- a/archinstall.py +++ b/archinstall.py @@ -891,11 +891,11 @@ def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): def strap_in_base(*positionals, **kwargs): if args['aur-support']: args['packages'] += ' git' - x = sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs) - print('Handle:', x) - print('Exit code:', x.exit_code, x.exit_code == 0) - if x.exit_code == 0: - if sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args), *positionals, **kwargs).exit_code == 0: + if sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs).exit_code == 0: + x = sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args), *positionals, **kwargs) + print(x) + print(x.exit_code) + if x.exit_code == 0: return True return False -- cgit v1.2.3-70-g09d2 From a543c2033c1e27ffa57b9762c63f792d6c2b451f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:17:31 +0000 Subject: Enhanced spawn logic a bit --- archinstall.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 26091ea8..ec371dee 100644 --- a/archinstall.py +++ b/archinstall.py @@ -292,7 +292,14 @@ class sys_command():#Thread): if not self.pid: # Child process # Replace child process with our main process if not self.kwargs['emulate']: - os.execv(self.cmd[0], self.cmd) + try: + os.execv(self.cmd[0], self.cmd) + except FileNotFoundError: + self.status = 'done' + log(f"{self.cmd[0]} does not exist.", origin='spawn', level=2) + self.exit_code = 1 + return False + os.chdir(old_dir) poller = epoll() -- cgit v1.2.3-70-g09d2 From fcdafd22e1ca2a51f3f9583f68fd02f2786f13e2 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:26:00 +0000 Subject: debug --- archinstall.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index ec371dee..26603be8 100644 --- a/archinstall.py +++ b/archinstall.py @@ -885,6 +885,9 @@ def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals mount_boot(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs) return True +def re_rank_mirrors(top=10, *positionals, **kwargs) + o = simple_command('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist') + def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): ## TODO: replace wget with urllib.request (no point in calling syscommand) country_list = [] @@ -892,7 +895,7 @@ def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): country_list.append(f'country={country}') o = simple_command(f"/usr/bin/wget 'https://www.archlinux.org/mirrorlist/?{'&'.join(country_list)}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist") o = simple_command("/usr/bin/sed -i 's/#Server/Server/' /root/mirrorlist") - o = simple_command('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist') + re_rank_mirrors(top, *positionals, **kwargs) return True def strap_in_base(*positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 76731be748e0a45203d038430588faad3f62bd87 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:26:34 +0000 Subject: debugging --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 26603be8..be7f8d55 100644 --- a/archinstall.py +++ b/archinstall.py @@ -885,7 +885,7 @@ def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals mount_boot(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs) return True -def re_rank_mirrors(top=10, *positionals, **kwargs) +def re_rank_mirrors(top=10, *positionals, **kwargs): o = simple_command('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist') def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 673e607d4b3d8fab76f93e58bbcada6e9c9e7d50 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:30:01 +0000 Subject: debugging --- archinstall.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/archinstall.py b/archinstall.py index be7f8d55..c9453bae 100644 --- a/archinstall.py +++ b/archinstall.py @@ -866,14 +866,14 @@ def mkfs_btrfs(drive='/dev/mapper/luksdev', *positionals, **kwargs): return True def mount_luksdev(where='/dev/mapper/luksdev', to='/mnt', *positionals, **kwargs): - o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt') # /dev/dm-0 + o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt')) # /dev/dm-0 if len(o) <= 0: o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt')) return True def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs): os.makedirs('/mnt/boot', exist_ok=True) - o = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot') # /dev/dm-0 + o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt/boot')) # /dev/dm-0 if len(o) <= 0: o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}')) return True @@ -886,15 +886,15 @@ def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals return True def re_rank_mirrors(top=10, *positionals, **kwargs): - o = simple_command('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist') + o = b''.join(sys_command(('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist'))) def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): ## TODO: replace wget with urllib.request (no point in calling syscommand) country_list = [] for country in countries.split(','): country_list.append(f'country={country}') - o = simple_command(f"/usr/bin/wget 'https://www.archlinux.org/mirrorlist/?{'&'.join(country_list)}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist") - o = simple_command("/usr/bin/sed -i 's/#Server/Server/' /root/mirrorlist") + o = b''.join(sys_command((f"/usr/bin/wget 'https://www.archlinux.org/mirrorlist/?{'&'.join(country_list)}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist"))) + o = b''.join(sys_command(("/usr/bin/sed -i 's/#Server/Server/' /root/mirrorlist"))) re_rank_mirrors(top, *positionals, **kwargs) return True -- cgit v1.2.3-70-g09d2 From 7bdb2cfb923fdf13cd199ed0508fd3413976ce50 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:35:27 +0000 Subject: More error handling --- archinstall.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index c9453bae..d94932a4 100644 --- a/archinstall.py +++ b/archinstall.py @@ -886,7 +886,9 @@ def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals return True def re_rank_mirrors(top=10, *positionals, **kwargs): - o = b''.join(sys_command(('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist'))) + if sys_command(('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist')).exit_code == 0: + return True + return False def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): ## TODO: replace wget with urllib.request (no point in calling syscommand) @@ -895,7 +897,9 @@ def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): country_list.append(f'country={country}') o = b''.join(sys_command((f"/usr/bin/wget 'https://www.archlinux.org/mirrorlist/?{'&'.join(country_list)}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist"))) o = b''.join(sys_command(("/usr/bin/sed -i 's/#Server/Server/' /root/mirrorlist"))) - re_rank_mirrors(top, *positionals, **kwargs) + + if not re_rank_mirrors(top, *positionals, **kwargs) or not os.path.isfile('/etc/pacman.d/mirrorlist'): + o = b''.join(sys_command(("/usr/bin/mv /root/mirrorlist /etc/pacman.d/"))) return True def strap_in_base(*positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 161f35d9bd0fde0917341d67c7f0f362d595309f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:41:49 +0000 Subject: debugging --- archinstall.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index d94932a4..fa184dd4 100644 --- a/archinstall.py +++ b/archinstall.py @@ -873,9 +873,11 @@ def mount_luksdev(where='/dev/mapper/luksdev', to='/mnt', *positionals, **kwargs def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs): os.makedirs('/mnt/boot', exist_ok=True) - o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt/boot')) # /dev/dm-0 + o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt/boot', *positionals, **kwargs)) # /dev/dm-0 + print('MOUNT STUFF:', o) if len(o) <= 0: - o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}')) + o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}', *positionals, **kwargs)) + print('MOUNT STUFF2:', o) return True def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 1c7077029b2cdce1d0e331c0d464a32ceb15533b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:46:27 +0000 Subject: debugging --- archinstall.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/archinstall.py b/archinstall.py index fa184dd4..68d59ecb 100644 --- a/archinstall.py +++ b/archinstall.py @@ -873,11 +873,15 @@ def mount_luksdev(where='/dev/mapper/luksdev', to='/mnt', *positionals, **kwargs def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs): os.makedirs('/mnt/boot', exist_ok=True) - o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt/boot', *positionals, **kwargs)) # /dev/dm-0 - print('MOUNT STUFF:', o) - if len(o) <= 0: - o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}', *positionals, **kwargs)) - print('MOUNT STUFF2:', o) + #o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt/boot', *positionals, **kwargs)) # /dev/dm-0 + + check_mount = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot', *positionals, **kwargs).decode('UTF-8').strip() + if len(check_mount): + return False + + o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}', *positionals, **kwargs)) + print('MOUNT STUFF2:', o) + return True def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 2fbf1beeef6db67ae9c7e3f302362dd5a43943dc Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:47:45 +0000 Subject: debugging --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 68d59ecb..6d67faea 100644 --- a/archinstall.py +++ b/archinstall.py @@ -193,7 +193,7 @@ def simple_command(cmd, opts=None, *positionals, **kwargs): if not opts: opts = {} if 'debug' in opts: print('[!] {}'.format(cmd)) - handle = Popen(cmd, shell='True', stdout=PIPE, stderr=STDOUT, stdin=PIPE, **kwargs) + handle = Popen(cmd, shell='True', stdout=PIPE, stderr=STDOUT, stdin=PIPE) output = b'' while handle.poll() is None: data = handle.stdout.read() -- cgit v1.2.3-70-g09d2 From 4a1a98b2ed2692e2b95eff649ea40c4415fd05cf Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:52:10 +0000 Subject: debugging --- archinstall.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/archinstall.py b/archinstall.py index 6d67faea..c8a45ea2 100644 --- a/archinstall.py +++ b/archinstall.py @@ -866,22 +866,22 @@ def mkfs_btrfs(drive='/dev/mapper/luksdev', *positionals, **kwargs): return True def mount_luksdev(where='/dev/mapper/luksdev', to='/mnt', *positionals, **kwargs): - o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt')) # /dev/dm-0 - if len(o) <= 0: - o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt')) + check_mounted = simple_command('/usr/bin/mount | /usr/bin/grep /mnt', *positionals, **kwargs).decode('UTF-8').strip()# /dev/dm-0 + if len(check_mounted): + return False + + o = b''.join(sys_command('/usr/bin/mount /dev/mapper/luksdev /mnt', *positionals, **kwargs)) return True def mount_boot(drive, partition, mountpoint='/mnt/boot', *positionals, **kwargs): os.makedirs('/mnt/boot', exist_ok=True) #o = b''.join(sys_command('/usr/bin/mount | /usr/bin/grep /mnt/boot', *positionals, **kwargs)) # /dev/dm-0 - check_mount = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot', *positionals, **kwargs).decode('UTF-8').strip() - if len(check_mount): + check_mounted = simple_command('/usr/bin/mount | /usr/bin/grep /mnt/boot', *positionals, **kwargs).decode('UTF-8').strip() + if len(check_mounted): return False o = b''.join(sys_command(f'/usr/bin/mount {drive}{partition} {mountpoint}', *positionals, **kwargs)) - print('MOUNT STUFF2:', o) - return True def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals, **kwargs): -- cgit v1.2.3-70-g09d2 From 8a5266d08751a0e1269ad0d812111bc3678c8959 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 00:54:42 +0000 Subject: debugging --- archinstall.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/archinstall.py b/archinstall.py index c8a45ea2..59e5cc81 100644 --- a/archinstall.py +++ b/archinstall.py @@ -624,19 +624,19 @@ def format_disk(drive='drive', start='start', end='size', emulate=False, *positi print(f'[N] Setting up {drive}.') # dd if=/dev/random of=args['drive'] bs=4096 status=progress # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda - if sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate).exit_code != 0: + if sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate, *positionals, **kwargs).exit_code != 0: return None - if sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate).exit_code != 0: + if sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate, *positionals, **kwargs).exit_code != 0: return None - if sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}', emulate=emulate).exit_code != 0: + if sys_command(f'/usr/bin/parted -s {drive} mkpart primary FAT32 1MiB {start}', emulate=emulate, *positionals, **kwargs).exit_code != 0: return None - if sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate).exit_code != 0: + if sys_command(f'/usr/bin/parted -s {drive} name 1 "EFI"', emulate=emulate, *positionals, **kwargs).exit_code != 0: return None - if sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate).exit_code != 0: + if sys_command(f'/usr/bin/parted -s {drive} set 1 esp on', emulate=emulate, *positionals, **kwargs).exit_code != 0: return None - if sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate).exit_code != 0: + if sys_command(f'/usr/bin/parted -s {drive} set 1 boot on', emulate=emulate, *positionals, **kwargs).exit_code != 0: return None - if sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {end}', emulate=emulate).exit_code != 0: + if sys_command(f'/usr/bin/parted -s {drive} mkpart primary {start} {end}', emulate=emulate, *positionals, **kwargs).exit_code != 0: return None # TODO: grab partitions after each parted/partition step instead of guessing which partiton is which later on. -- cgit v1.2.3-70-g09d2 From 86847d6dc17d83549be19b0cf54bda4711ceccec Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 01:05:04 +0000 Subject: Added extra error handling in case filesystem wasn't mounted porperly --- archinstall.py | 1 + 1 file changed, 1 insertion(+) diff --git a/archinstall.py b/archinstall.py index 59e5cc81..4f2dc19a 100644 --- a/archinstall.py +++ b/archinstall.py @@ -612,6 +612,7 @@ def human_disk_info(drive): } def close_disks(): + o = simple_command('/usr/bin/umount -R /mnt/boot') o = simple_command('/usr/bin/umount -R /mnt') o = simple_command('/usr/bin/cryptsetup close /dev/mapper/luksdev') -- cgit v1.2.3-70-g09d2 From 6b570b62c2556932451f404f62cd31068dd1a3b0 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 01:06:23 +0000 Subject: Removed some debugging --- archinstall.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/archinstall.py b/archinstall.py index 4f2dc19a..83193aa7 100644 --- a/archinstall.py +++ b/archinstall.py @@ -622,7 +622,6 @@ def format_disk(drive='drive', start='start', end='size', emulate=False, *positi end = args[end] if not drive: raise ValueError('Need to supply a drive path, for instance: /dev/sdx') - print(f'[N] Setting up {drive}.') # dd if=/dev/random of=args['drive'] bs=4096 status=progress # https://github.com/dcantrell/pyparted would be nice, but isn't officially in the repo's #SadPanda if sys_command(f'/usr/bin/parted -s {drive} mklabel gpt', emulate=emulate, *positionals, **kwargs).exit_code != 0: @@ -914,8 +913,6 @@ def strap_in_base(*positionals, **kwargs): args['packages'] += ' git' if sys_command('/usr/bin/pacman -Syy', *positionals, **kwargs).exit_code == 0: x = sys_command('/usr/bin/pacstrap /mnt base base-devel linux linux-firmware btrfs-progs efibootmgr nano wpa_supplicant dialog {packages}'.format(**args), *positionals, **kwargs) - print(x) - print(x.exit_code) if x.exit_code == 0: return True return False @@ -1134,6 +1131,7 @@ if __name__ == '__main__': time.sleep(1) close_disks() + print(f'[N] Setting up {drive}.') format_disk('drive', start='start', end='size') refresh_partition_list('drive') -- cgit v1.2.3-70-g09d2 From b3e9505fab33af0e2420c98cea9b0b5dc9949677 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 19 Nov 2019 01:14:08 +0000 Subject: Cleaned up function calls a bit --- archinstall.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/archinstall.py b/archinstall.py index 83193aa7..2b3cc302 100644 --- a/archinstall.py +++ b/archinstall.py @@ -892,20 +892,22 @@ def mount_mountpoints(drive, bootpartition, mountpoint='/mnt/boot', *positionals return True def re_rank_mirrors(top=10, *positionals, **kwargs): - if sys_command(('/usr/bin/rankmirrors -n {top} /root/mirrorlist > /etc/pacman.d/mirrorlist')).exit_code == 0: + if sys_command(('/usr/bin/rankmirrors -n {top} /etc/pacman.d/mirrorlist > /etc/pacman.d/mirrorlist')).exit_code == 0: return True return False -def filter_mirrors_by_country(countries, top=10, *positionals, **kwargs): +def filter_mirrors_by_country_list(countries, top=None, *positionals, **kwargs): ## TODO: replace wget with urllib.request (no point in calling syscommand) country_list = [] for country in countries.split(','): country_list.append(f'country={country}') o = b''.join(sys_command((f"/usr/bin/wget 'https://www.archlinux.org/mirrorlist/?{'&'.join(country_list)}&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on' -O /root/mirrorlist"))) o = b''.join(sys_command(("/usr/bin/sed -i 's/#Server/Server/' /root/mirrorlist"))) + o = b''.join(sys_command(("/usr/bin/mv /root/mirrorlist /etc/pacman.d/"))) - if not re_rank_mirrors(top, *positionals, **kwargs) or not os.path.isfile('/etc/pacman.d/mirrorlist'): - o = b''.join(sys_command(("/usr/bin/mv /root/mirrorlist /etc/pacman.d/"))) + if top: + re_rank_mirrors(top, *positionals, **kwargs) or not os.path.isfile('/etc/pacman.d/mirrorlist') + return True def strap_in_base(*positionals, **kwargs): @@ -1167,7 +1169,7 @@ if __name__ == '__main__': if 'mirrors' in args and args['mirrors'] and 'country' in args and get_default_gateway_linux(): print('[N] Reordering mirrors.') - filter_mirrors_by_country(args['country']) + filter_mirrors_by_country_list([args['country']]) pre_conf = {} if 'pre' in instructions: -- cgit v1.2.3-70-g09d2 From 53a57300cc3e322d9e10ce30ad03a8b00d7a0009 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 23 Nov 2019 21:31:29 +0000 Subject: Fixed which statement. It's a builtin and not a /usr/bin command --- archinstall.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/archinstall.py b/archinstall.py index 2b3cc302..783db347 100644 --- a/archinstall.py +++ b/archinstall.py @@ -7,7 +7,7 @@ from glob import glob from select import epoll, EPOLLIN, EPOLLHUP from socket import socket, inet_ntoa, AF_INET, AF_INET6, AF_PACKET from collections import OrderedDict as oDict -from subprocess import Popen, STDOUT, PIPE +from subprocess import Popen, STDOUT, PIPE, check_output from random import choice from string import ascii_uppercase, ascii_lowercase, digits from hashlib import sha512 @@ -235,9 +235,10 @@ class sys_command():#Thread): if not self.cmd[0][0] == '/': log('Worker command is not executed with absolute path, trying to find: {}'.format(self.cmd[0]), origin='spawn', level=5) - o = sys_command('/usr/bin/which {}'.format(self.cmd[0]), emulate=False, hide_from_log=True) + o = check_output(['which', self.cmd[0]]) + ##o = sys_command('sh which {}'.format(self.cmd[0]), emulate=False, hide_from_log=True) log('This is the binary {} for {}'.format(o.decode('UTF-8'), self.cmd[0]), origin='spawn', level=5) - self.cmd[0] = o.decode('UTF-8') + self.cmd[0] = o.decode('UTF-8').strip() if not os.path.isdir(self.exec_dir): os.makedirs(self.exec_dir) -- cgit v1.2.3-70-g09d2 From 5c306c3bccf80a74756d13c06da7baa2e91f5256 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 23 Nov 2019 21:36:07 +0000 Subject: Fixed which statement. It's a builtin and not a /usr/bin command --- archinstall.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/archinstall.py b/archinstall.py index 783db347..fa700ffe 100644 --- a/archinstall.py +++ b/archinstall.py @@ -235,8 +235,10 @@ class sys_command():#Thread): if not self.cmd[0][0] == '/': log('Worker command is not executed with absolute path, trying to find: {}'.format(self.cmd[0]), origin='spawn', level=5) - o = check_output(['which', self.cmd[0]]) - ##o = sys_command('sh which {}'.format(self.cmd[0]), emulate=False, hide_from_log=True) + x = Popen(f'/usr/bin/sh -c "which {self.cmd[0]}"', shell=True, stdout=PIPE) + while x.poll() is None: + pass + o = x.stdout.read() log('This is the binary {} for {}'.format(o.decode('UTF-8'), self.cmd[0]), origin='spawn', level=5) self.cmd[0] = o.decode('UTF-8').strip() -- cgit v1.2.3-70-g09d2 From 5e99895803accce102faeaac5544f76ed54a904d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 23 Nov 2019 21:38:30 +0000 Subject: Fixed which statement. It's a builtin and not a /usr/bin command --- archinstall.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/archinstall.py b/archinstall.py index fa700ffe..c7b54d12 100644 --- a/archinstall.py +++ b/archinstall.py @@ -235,10 +235,7 @@ class sys_command():#Thread): if not self.cmd[0][0] == '/': log('Worker command is not executed with absolute path, trying to find: {}'.format(self.cmd[0]), origin='spawn', level=5) - x = Popen(f'/usr/bin/sh -c "which {self.cmd[0]}"', shell=True, stdout=PIPE) - while x.poll() is None: - pass - o = x.stdout.read() + o = check_output(['which', self.cmd[0]]) log('This is the binary {} for {}'.format(o.decode('UTF-8'), self.cmd[0]), origin='spawn', level=5) self.cmd[0] = o.decode('UTF-8').strip() -- cgit v1.2.3-70-g09d2 From bbb62bc8798bb874835dcbde711d09311b44ae3f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 23 Nov 2019 21:38:53 +0000 Subject: Fixed which statement. It's a builtin and not a /usr/bin command --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index c7b54d12..80ea9f07 100644 --- a/archinstall.py +++ b/archinstall.py @@ -235,7 +235,7 @@ class sys_command():#Thread): if not self.cmd[0][0] == '/': log('Worker command is not executed with absolute path, trying to find: {}'.format(self.cmd[0]), origin='spawn', level=5) - o = check_output(['which', self.cmd[0]]) + o = check_output(['/usr/bin/which', self.cmd[0]]) log('This is the binary {} for {}'.format(o.decode('UTF-8'), self.cmd[0]), origin='spawn', level=5) self.cmd[0] = o.decode('UTF-8').strip() -- cgit v1.2.3-70-g09d2 From 97f8f642f7c33eee4f4f9260085f6f95790988d7 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 27 Nov 2019 19:06:12 +0000 Subject: Fixes for transition --- archinstall.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/archinstall.py b/archinstall.py index 80ea9f07..2b27f8be 100644 --- a/archinstall.py +++ b/archinstall.py @@ -410,7 +410,7 @@ class sys_command():#Thread): #self.callback(self, *self.args, **self.kwargs) -def get_drive_from_uuid(uuid): +def get_drive_from_uuid(drive): if len(harddrives) <= 0: raise ValueError("No hard drives to iterate in order to find: {}".format(uuid)) for drive in harddrives: @@ -1133,14 +1133,14 @@ if __name__ == '__main__': time.sleep(1) close_disks() - print(f'[N] Setting up {drive}.') + print(f'[N] Setting up {args["drive"]}.') format_disk('drive', start='start', end='size') refresh_partition_list('drive') print(f'Partitions: (Boot: {list(args["partitions"].keys())[0]})') if len(args['partitions']) <= 0: - print('[E] No partitions were created on {drive}'.format(**args), o) + print(f'[E] No partitions were created on {args["drive"]}', o) exit(1) if not args['rerun'] or args['ignore-rerun']: @@ -1150,7 +1150,7 @@ if __name__ == '__main__': # "--cipher sha512" breaks the shit. # TODO: --use-random instead of --use-urandom - print(f'[N] Adding encryption to {drive}{partitions["2"]}.') + print(f'[N] Adding encryption to {args["drive"]}{partitions["2"]}.') if not encrypt_partition('drive', '2', 'pwfile'): print('[E] Failed to setup disk encryption.', o) exit(1) -- cgit v1.2.3-70-g09d2 From 2f30f907f400a5a439bf61da1c435f3f31a95d43 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 27 Nov 2019 19:07:18 +0000 Subject: Fixes for transition --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index 2b27f8be..a4b73c56 100644 --- a/archinstall.py +++ b/archinstall.py @@ -1144,7 +1144,7 @@ if __name__ == '__main__': exit(1) if not args['rerun'] or args['ignore-rerun']: - if not mkfs_fat32('drive', '1', *positionals, **kwargs): + if not mkfs_fat32('drive', '1'): print(f'[E] Could not setup {args["drive"]}{args["partitions"]["1"]}') exit(1) -- cgit v1.2.3-70-g09d2 From 20fdb8afeedd53e07f8f5ba18aee526486294f0d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 27 Nov 2019 19:09:13 +0000 Subject: Fixes for transition --- archinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index a4b73c56..e86d0763 100644 --- a/archinstall.py +++ b/archinstall.py @@ -1150,7 +1150,7 @@ if __name__ == '__main__': # "--cipher sha512" breaks the shit. # TODO: --use-random instead of --use-urandom - print(f'[N] Adding encryption to {args["drive"]}{partitions["2"]}.') + print(f'[N] Adding encryption to {args["drive"]}{args["partitions"]["2"]}.') if not encrypt_partition('drive', '2', 'pwfile'): print('[E] Failed to setup disk encryption.', o) exit(1) -- cgit v1.2.3-70-g09d2 From f5c3bda6036d1d123a57b104011f725f644eab94 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 27 Nov 2019 19:32:49 +0000 Subject: New feature: phone-home (post status POST request, optional.. Useful for debugging / verifying installs) --- archinstall.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index e86d0763..c6f6fea7 100644 --- a/archinstall.py +++ b/archinstall.py @@ -755,6 +755,7 @@ def setup_args_defaults(args, interactive=True): if not 'aur-support' in args: args['aur-support'] = True # Support adds yay (https://github.com/Jguer/yay) in installation steps. if not 'ignore-rerun' in args: args['ignore-rerun'] = False if not 'localtime' in args: args['localtime'] = 'Europe/Stockholm' if args['country'] == 'SE' else 'GMT+0' # TODO: Arbitrary for now + if not 'phone-home' in args: args['phone-home'] = False if not 'drive' in args: if interactive and len(harddrives): drives = sorted(list(harddrives.keys())) @@ -1218,7 +1219,9 @@ if __name__ == '__main__': if not args['rerun'] or rerun: print('[N] Straping in packages.') - strap_in_base() # TODO: check return here? we return based off pacstrap exit code.. Never tired it tho. + base_return_code = strap_in_base() # TODO: check return here? we return based off pacstrap exit code.. Never tired it tho. + else: + base_return_code = None if not os.path.isdir('/mnt/etc'): # TODO: This might not be the most long term stable thing to rely on... print('[E] Failed to strap in packages', o) @@ -1254,3 +1257,15 @@ if __name__ == '__main__': o = simple_command('/usr/bin/reboot now') else: print('Done. "umount -R /mnt; reboot" when you\'re done tinkering.') + + if args['phone-home']: + payload = json.dumps({"hostname": args['hostname'], + "done" : time(), + "profile": args['profile'], + "drive": args['drive'], + "base_status": base_return_code + }).encode('utf8') + request = urllib.request.Request(args['phone-home'], + data=payload, + headers={'content-type': 'application/json'}) + response = urllib.request.urlopen(request) \ No newline at end of file -- cgit v1.2.3-70-g09d2 From d7e5da5467268fa154d2b04beb0f1a8cf6f42079 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 27 Nov 2019 20:38:03 +0000 Subject: Fixes for transition --- archinstall.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/archinstall.py b/archinstall.py index c6f6fea7..79e4faf8 100644 --- a/archinstall.py +++ b/archinstall.py @@ -1268,4 +1268,6 @@ if __name__ == '__main__': request = urllib.request.Request(args['phone-home'], data=payload, headers={'content-type': 'application/json'}) - response = urllib.request.urlopen(request) \ No newline at end of file + response = urllib.request.urlopen(request) + print(response) + time.sleep(2) \ No newline at end of file -- cgit v1.2.3-70-g09d2 From db24153dd7d610d86909b21c13698ca1675c823a Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 27 Nov 2019 21:02:53 +0000 Subject: Fixes for transition --- archinstall.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/archinstall.py b/archinstall.py index 79e4faf8..d4d55021 100644 --- a/archinstall.py +++ b/archinstall.py @@ -1244,6 +1244,20 @@ if __name__ == '__main__': o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"')) o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"')) + if args['phone-home']: + payload = json.dumps({"hostname": args['hostname'], + "done" : time.time(), + "profile": args['profile'], + "drive": args['drive'], + "base_status": base_return_code + }).encode('utf8') + request = urllib.request.Request(args['phone-home'], + data=payload, + headers={'content-type': 'application/json'}) + response = urllib.request.urlopen(request) + print(response) + time.sleep(2) + ## == Passwords # o = sys_command('arch-chroot /mnt usermod --password {} root'.format(args['password'])) # o = sys_command("arch-chroot /mnt sh -c 'echo {pin} | passwd --stdin root'".format(pin='"{pin}"'.format(**args, pin=args['password'])), echo=True) @@ -1257,17 +1271,3 @@ if __name__ == '__main__': o = simple_command('/usr/bin/reboot now') else: print('Done. "umount -R /mnt; reboot" when you\'re done tinkering.') - - if args['phone-home']: - payload = json.dumps({"hostname": args['hostname'], - "done" : time(), - "profile": args['profile'], - "drive": args['drive'], - "base_status": base_return_code - }).encode('utf8') - request = urllib.request.Request(args['phone-home'], - data=payload, - headers={'content-type': 'application/json'}) - response = urllib.request.urlopen(request) - print(response) - time.sleep(2) \ No newline at end of file -- cgit v1.2.3-70-g09d2 From bc154eacbe983231282d83e7ee5ae40c6128f026 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 27 Nov 2019 21:22:16 +0000 Subject: Fixes for transition --- archinstall.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/archinstall.py b/archinstall.py index d4d55021..38856973 100644 --- a/archinstall.py +++ b/archinstall.py @@ -739,6 +739,15 @@ def merge_dicts(d1, d2, before=True, overwrite=False): def random_string(l): return ''.join(choice(ascii_uppercase + ascii_lowercase + digits) for i in range(l)) +def phone_home(url): + payload = json.dumps({"hostname": args['hostname'], + "done" : time.time(), + "profile": args['profile'], + "drive": args['drive'], + "base_status": base_return_code}).encode('utf8') + request = urllib.request.Request(url, data=payload, headers={'content-type': 'application/json'}) + response = urllib.request.urlopen(request) + def setup_args_defaults(args, interactive=True): if not 'size' in args: args['size'] = '100%' if not 'start' in args: args['start'] = '513MiB' @@ -752,6 +761,7 @@ def setup_args_defaults(args, interactive=True): if not 'profile' in args: args['profile'] = None if not 'profiles-path' in args: args['profiles-path'] = profiles_path if not 'rerun' in args: args['rerun'] = None + if not 'aur-keep' in args: args['aur-keep'] = False if not 'aur-support' in args: args['aur-support'] = True # Support adds yay (https://github.com/Jguer/yay) in installation steps. if not 'ignore-rerun' in args: args['ignore-rerun'] = False if not 'localtime' in args: args['localtime'] = 'Europe/Stockholm' if args['country'] == 'SE' else 'GMT+0' # TODO: Arbitrary for now @@ -1228,36 +1238,29 @@ if __name__ == '__main__': exit(1) if not args['rerun'] or rerun: + print('[N] Configuring base system.') configure_base_system() ## WORKAROUND: https://github.com/systemd/systemd/issues/13603#issuecomment-552246188 + print('[N] Setting up bootloader.') setup_bootloader() if args['aur-support']: print('[N] AUR support demanded, building "yay" before running POST steps.') add_AUR_support() print('[N] AUR support added. use "yay -Syy --noconfirm " to deploy in POST.') - + + print('[N] Running post installation steps.') run_post_install_steps() + time.sleep(2) - if args['aur-support']: + if args['aur-support'] and not args['aur-keep']: o = b''.join(sys_command('/usr/bin/sed -i \'s/%wheel ALL=(ALL) NO/# %wheel ALL=(ALL) NO/\' /mnt/etc/sudoers')) o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "userdel aibuilder"')) o = b''.join(sys_command('/usr/bin/arch-chroot /mnt sh -c "rm -rf /home/aibuilder"')) if args['phone-home']: - payload = json.dumps({"hostname": args['hostname'], - "done" : time.time(), - "profile": args['profile'], - "drive": args['drive'], - "base_status": base_return_code - }).encode('utf8') - request = urllib.request.Request(args['phone-home'], - data=payload, - headers={'content-type': 'application/json'}) - response = urllib.request.urlopen(request) - print(response) - time.sleep(2) - + phone_home(args['phone-home']) + ## == Passwords # o = sys_command('arch-chroot /mnt usermod --password {} root'.format(args['password'])) # o = sys_command("arch-chroot /mnt sh -c 'echo {pin} | passwd --stdin root'".format(pin='"{pin}"'.format(**args, pin=args['password'])), echo=True) -- cgit v1.2.3-70-g09d2