index : archinstall32 | |
Archlinux32 installer | gitolite user |
summaryrefslogtreecommitdiff |
author | Anton Hvornum <anton.feeds+github@gmail.com> | 2020-10-18 21:24:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-18 21:24:46 +0200 |
commit | f32f1e238a0a36b0d1b5220df6f6f053c6c4168c (patch) | |
tree | 78053ae908629bb49725246fcb2e957875d9ec3b | |
parent | 3ba6e69e051e4614ebf18f7f08c0d7a18366d9b7 (diff) | |
parent | 06ee896c6c58e877325896b33a2a3dd3eb0a1727 (diff) |
-rw-r--r-- | archinstall/lib/disk.py | 10 | ||||
-rw-r--r-- | archinstall/lib/general.py | 38 | ||||
-rw-r--r-- | archinstall/lib/profiles.py | 3 | ||||
-rw-r--r-- | examples/guided.py | 87 |
diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 7cd8dd0f..b11f2318 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -25,6 +25,16 @@ class BlockDevice(): raise KeyError(f'{self} does not contain information: "{key}"') return self.info[key] + def json(self): + """ + json() has precedence over __dump__, so this is a way + to give less/partial information for user readability. + """ + return { + 'path' : self.path, + 'size' : self.info['size'] if 'size' in self.info else '<unknown>' + } + def __dump__(self): return { 'path' : self.path, diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index 393bf69a..ff834241 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -1,5 +1,6 @@ import os, json, hashlib, shlex, sys import time, pty +from datetime import datetime, date from subprocess import Popen, STDOUT, PIPE, check_output from select import epoll, EPOLLIN, EPOLLHUP from .exceptions import * @@ -30,6 +31,43 @@ def locate_binary(name): return os.path.join(root, file) break # Don't recurse +class JSON_Encoder: + def _encode(obj): + if isinstance(obj, dict): + ## We'll need to iterate not just the value that default() usually gets passed + ## But also iterate manually over each key: value pair in order to trap the keys. + + for key, val in list(obj.items()): + if isinstance(val, dict): + val = json.loads(json.dumps(val, cls=JSON)) # This, is a EXTREMELY ugly hack.. + # But it's the only quick way I can think of to + # trigger a encoding of sub-dictionaries. + else: + val = JSON_Encoder._encode(val) + del(obj[key]) + obj[JSON_Encoder._encode(key)] = val + return obj + elif hasattr(obj, 'json'): + return obj.json() + elif hasattr(obj, '__dump__'): + return obj.__dump__() + elif isinstance(obj, (datetime, date)): + return obj.isoformat() + elif isinstance(obj, (list, set, tuple)): + r = [] + for item in obj: + r.append(json.loads(json.dumps(item, cls=JSON))) + return r + else: + return obj + +class JSON(json.JSONEncoder, json.JSONDecoder): + def _encode(self, obj): + return JSON_Encoder._encode(obj) + + def encode(self, obj): + return super(JSON, self).encode(self._encode(obj)) + class sys_command():#Thread): """ Stolen from archinstall_gui diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 47e6dd36..e018f753 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -61,6 +61,9 @@ class Profile(): self._cache = None self.args = args + def __dump__(self, *args, **kwargs): + return {'path' : self._path} + def __repr__(self, *args, **kwargs): return f'Profile({self._path} <"{self.path}">)' diff --git a/examples/guided.py b/examples/guided.py index 30514a71..cc660b90 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -1,4 +1,20 @@ -import archinstall, getpass, time +import archinstall +import getpass, time, json, sys, signal + +""" +This signal-handler chain (and global variable) +is used to trigger the "Are you sure you want to abort?" question. +""" +SIG_TRIGGER = False +def kill_handler(sig, frame): + print() + exit(0) +def sig_handler(sig, frame): + global SIG_TRIGGER + SIG_TRIGGER = True + signal.signal(signal.SIGINT, kill_handler) +original_sigint_handler = signal.getsignal(signal.SIGINT) +signal.signal(signal.SIGINT, sig_handler) def perform_installation(device, boot_partition, language, mirrors): """ @@ -50,8 +66,13 @@ archinstall.sys_command(f'cryptsetup close /dev/mapper/luksloop', surpress_error keyboard_language = archinstall.select_language(archinstall.list_keyboard_languages()) archinstall.set_keyboard_language(keyboard_language) +# Create a storage structure for all our information. +# We'll print this right before the user gets informed about the formatting timer. +archinstall.storage['_guided'] = {} + # Set which region to download packages from during the installation mirror_regions = archinstall.select_mirror_regions(archinstall.list_mirrors()) +archinstall.storage['_guided']['mirrors'] = mirror_regions # Ask which harddrive/block-device we will install to harddrive = archinstall.select_disk(archinstall.all_disks()) @@ -61,10 +82,12 @@ while (disk_password := getpass.getpass(prompt='Enter disk encryption password ( archinstall.log(' * Passwords did not match * ', bg='black', fg='red') continue break +archinstall.storage['_guided']['harddrive'] = harddrive # Ask for a hostname hostname = input('Desired hostname for the installation: ') if len(hostname) == 0: hostname = 'ArchInstall' +archinstall.storage['_guided']['hostname'] = hostname # Ask for a root password (optional, but triggers requirement for super-user if skipped) while (root_pw := getpass.getpass(prompt='Enter root password (leave blank to leave root disabled): ')): @@ -87,6 +110,10 @@ while 1: archinstall.log(' * Since root is disabled, you need to create a least one (super) user!', bg='black', fg='red') continue break + + if 'users' not in archinstall.storage['_guided']: archinstall.storage['_guided']['users'] = [] + archinstall.storage['_guided']['users'].append(new_user) + new_user_passwd = getpass.getpass(prompt=f'Password for user {new_user}: ') new_user_passwd_verify = getpass.getpass(prompt=f'Enter password again for verification: ') if new_user_passwd != new_user_passwd_verify: @@ -99,12 +126,17 @@ while 1: # Ask for archinstall-specific profiles (such as desktop environments etc) while 1: profile = archinstall.select_profile(archinstall.list_profiles()) - if profile and type(profile) != str: # Got a imported profile - if not profile[1]._prep_function(): - archinstall.log(' * Profile\'s preperation requirements was not fulfilled.', bg='black', fg='red') - continue - profile = profile[0]._path # Once the prep is done, replace the selected profile with the profile name ("path") given from select_profile() - break + if profile: + archinstall.storage['_guided']['profile'] = profile + + if type(profile) != str: # Got a imported profile + archinstall.storage['_guided']['profile'] = profile[0] # The second return is a module, and not a handle/object. + if not profile[1]._prep_function(): + archinstall.log(' * Profile\'s preperation requirements was not fulfilled.', bg='black', fg='red') + continue + + profile = profile[0]._path # Once the prep is done, replace the selected profile with the profile name ("path") given from select_profile() + break else: break @@ -117,27 +149,42 @@ while 1: try: if archinstall.validate_package_list(packages): + archinstall.storage['_guided']['packages'] = packages break except archinstall.RequirementError as e: print(e) -# TODO: Print a summary here of all the options chosen. -# Ideally, archinstall should keep track of this internally -# and there should be something like print(archinstall.config). +print() +print('This is your chosen configuration:') +print(json.dumps(archinstall.storage['_guided'], indent=4, sort_keys=True, cls=archinstall.JSON)) +print() """ Issue a final warning before we continue with something un-revertable. + We mention the drive one last time, and count from 5 to 0. """ -print(f' ! Formatting {harddrive} in 5...') -time.sleep(1) -print(f' ! Formatting {harddrive} in 4...') -time.sleep(1) -print(f' ! Formatting {harddrive} in 3...') -time.sleep(1) -print(f' ! Formatting {harddrive} in 2...') -time.sleep(1) -print(f' ! Formatting {harddrive} in 1...') -time.sleep(1) + +print(f' ! Formatting {harddrive} in ', end='') + +for i in range(5, 0, -1): + print(f"{i}", end='') + + for x in range(4): + sys.stdout.flush() + time.sleep(0.25) + print(".", end='') + + if SIG_TRIGGER: + abort = input('\nDo you really want to abort (y/n)? ') + if abort.strip() != 'n': + exit(0) + + if SIG_TRIGGER is False: + sys.stdin.read() + SIG_TRIGGER = False + signal.signal(signal.SIGINT, sig_handler) +print() +signal.signal(signal.SIGINT, original_sigint_handler) """ Setup the blockdevice, filesystem (and optionally encryption). |