From 9d7962f39c1d8d8321da9c3653ca7e8d1def5c9b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 4 Aug 2020 14:30:15 +0200 Subject: Added a list_profiles() function, that lists all current local profiles. Also removed support for .json as it's redundant for the future. --- archinstall/lib/profiles.py | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) (limited to 'archinstall/lib/profiles.py') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index c1e2f8a9..f0de62d3 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -14,6 +14,16 @@ def grab_url_data(path): response = urllib.request.urlopen(safe_path, context=ssl_context) return response.read() +def list_profiles(base='./profiles/'): + # TODO: Grab from github page as well, not just local static files + cache = {} + for root, folders, files in os.walk(base): + for file in files: + if os.path.splitext(file)[1] == '.py': + cache[file] = os.path.join(root, file) + break + return cache + class Imported(): def __init__(self, spec, imported): self.spec = spec @@ -44,8 +54,6 @@ class Profile(): return os.path.abspath(f'{self.name}') for path in ['./profiles', '/etc/archinstall', '/etc/archinstall/profiles', os.path.abspath(f'{os.path.dirname(__file__)}/../profiles')]: # Step out of /lib - if os.path.isfile(f'{path}/{self.name}.json'): - return os.path.abspath(f'{path}/{self.name}.json') elif os.path.isfile(f'{path}/{self.name}.py'): return os.path.abspath(f'{path}/{self.name}.py') @@ -55,18 +63,6 @@ class Profile(): return f'{UPSTREAM_URL}/{self.name}.py' except urllib.error.HTTPError: pass - try: - if (cache := grab_url_data(f'{UPSTREAM_URL}/{self.name}.json')): - self._cache = cache - return f'{UPSTREAM_URL}/{self.name}.json' - except urllib.error.HTTPError: - pass - try: - if (cache := grab_url_data(f'{UPSTREAM_URL}/{self.name}.json')): - self._cache = cache - return f'{UPSTREAM_URL}/{self.name}.json' - except urllib.error.HTTPError: - pass return None @@ -80,11 +76,8 @@ class Profile(): imported = importlib.util.module_from_spec(spec) sys.modules[os.path.basename(absolute_path)] = imported return Imported(spec, imported) - elif absolute_path[:4] == 'http': - return json.loads(self._cache) - - with open(absolute_path, 'r') as fh: - return json.load(fh) + else: + raise ProfileError(f'Extension {os.path.splitext(absolute_path)[1]} is not a supported profile model. Only .py is supported.') raise ProfileError(f'No such profile ({self.name}) was found either locally or in {UPSTREAM_URL}') @@ -190,8 +183,6 @@ class Application(Profile): for path in ['./applications', './profiles/applications', '/etc/archinstall/applications', '/etc/archinstall/profiles/applications', os.path.abspath(f'{os.path.dirname(__file__)}/../profiles/applications')]: if os.path.isfile(f'{path}/{self.name}.py'): return os.path.abspath(f'{path}/{self.name}.py') - elif os.path.isfile(f'{path}/{self.name}.json'): - return os.path.abspath(f'{path}/{self.name}.json') try: if (cache := grab_url_data(f'{UPSTREAM_URL}/applications/{self.name}.py')): @@ -199,11 +190,5 @@ class Application(Profile): return f'{UPSTREAM_URL}/applications/{self.name}.py' except urllib.error.HTTPError: pass - try: - if (cache := grab_url_data(f'{UPSTREAM_URL}/applications/{self.name}.json')): - self._cache = cache - return f'{UPSTREAM_URL}/applications/{self.name}.json' - except urllib.error.HTTPError: - pass return None \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 44e920297b2fd6f929e379025cd239baa0d41cc5 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 4 Aug 2020 14:41:11 +0200 Subject: elif mixup --- archinstall/lib/profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/profiles.py') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index f0de62d3..0e76ba3d 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -54,7 +54,7 @@ class Profile(): return os.path.abspath(f'{self.name}') for path in ['./profiles', '/etc/archinstall', '/etc/archinstall/profiles', os.path.abspath(f'{os.path.dirname(__file__)}/../profiles')]: # Step out of /lib - elif os.path.isfile(f'{path}/{self.name}.py'): + if os.path.isfile(f'{path}/{self.name}.py'): return os.path.abspath(f'{path}/{self.name}.py') try: -- cgit v1.2.3-70-g09d2 From b2a8fd985746a06ccbdfe87f7f1d4c780fdaaabc Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 4 Aug 2020 14:50:36 +0200 Subject: Adding description handling in profiles. --- archinstall/lib/profiles.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'archinstall/lib/profiles.py') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 0e76ba3d..4e14ea67 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -20,7 +20,13 @@ def list_profiles(base='./profiles/'): for root, folders, files in os.walk(base): for file in files: if os.path.splitext(file)[1] == '.py': - cache[file] = os.path.join(root, file) + description = '' + with open(os.path.join(root, file), 'r') as fh: + first_line = fh.readline() + if first_line[0] == '#': + description = first_line.strip() + + cache[file] = {'path' : os.path.join(root, file), 'description' : ''} break return cache -- cgit v1.2.3-70-g09d2 From 2af2f90280dbe035586fac71cc9387d2d823cf3c Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 4 Aug 2020 14:56:50 +0200 Subject: Added a debug --- archinstall/lib/profiles.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'archinstall/lib/profiles.py') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 4e14ea67..ed8e317b 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -23,9 +23,10 @@ def list_profiles(base='./profiles/'): description = '' with open(os.path.join(root, file), 'r') as fh: first_line = fh.readline() + print(first_line) if first_line[0] == '#': description = first_line.strip() - + cache[file] = {'path' : os.path.join(root, file), 'description' : ''} break return cache -- cgit v1.2.3-70-g09d2 From b29c35de23c1334b693e71456f199937af4ba4ab Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 4 Aug 2020 14:57:33 +0200 Subject: Fixed description support --- archinstall/lib/profiles.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'archinstall/lib/profiles.py') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index ed8e317b..1f55facd 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -23,11 +23,10 @@ def list_profiles(base='./profiles/'): description = '' with open(os.path.join(root, file), 'r') as fh: first_line = fh.readline() - print(first_line) if first_line[0] == '#': description = first_line.strip() - cache[file] = {'path' : os.path.join(root, file), 'description' : ''} + cache[file] = {'path' : os.path.join(root, file), 'description' : description} break return cache -- cgit v1.2.3-70-g09d2 From 11f36102db539ea8648a5aeaf2b799b554b3e272 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Tue, 4 Aug 2020 14:58:10 +0200 Subject: Fixed description support --- archinstall/lib/profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/profiles.py') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 1f55facd..3360d4bb 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -24,7 +24,7 @@ def list_profiles(base='./profiles/'): with open(os.path.join(root, file), 'r') as fh: first_line = fh.readline() if first_line[0] == '#': - description = first_line.strip() + description = first_line[1:].strip() cache[file] = {'path' : os.path.join(root, file), 'description' : description} break -- cgit v1.2.3-70-g09d2 From 27e20ae433ba3d374c5e5eefca77c5bc320fd64e Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Wed, 5 Aug 2020 10:29:34 +0200 Subject: Removed support entirely for .json. Cleaning up the Profile() class **a lot**. Also tweaked some variable names to better suit the actual usage, which was a path definition not a name definition anymore --- archinstall/lib/profiles.py | 109 ++++++++------------------------------------ 1 file changed, 19 insertions(+), 90 deletions(-) (limited to 'archinstall/lib/profiles.py') diff --git a/archinstall/lib/profiles.py b/archinstall/lib/profiles.py index 3360d4bb..47d6eaf8 100644 --- a/archinstall/lib/profiles.py +++ b/archinstall/lib/profiles.py @@ -45,28 +45,28 @@ class Imported(): raise args[1] class Profile(): - def __init__(self, installer, name, args={}): - self.name = name + def __init__(self, installer, path, args={}): + self._path = path self.installer = installer self._cache = None self.args = args def __repr__(self, *args, **kwargs): - return f'Profile({self.name} <"{self.path}">)' + return f'Profile({self._path} <"{self.path}">)' @property def path(self, *args, **kwargs): - if os.path.isfile(f'{self.name}'): - return os.path.abspath(f'{self.name}') + if os.path.isfile(f'{self._path}'): + return os.path.abspath(f'{self._path}') for path in ['./profiles', '/etc/archinstall', '/etc/archinstall/profiles', os.path.abspath(f'{os.path.dirname(__file__)}/../profiles')]: # Step out of /lib - if os.path.isfile(f'{path}/{self.name}.py'): - return os.path.abspath(f'{path}/{self.name}.py') + if os.path.isfile(f'{path}/{self._path}.py'): + return os.path.abspath(f'{path}/{self._path}.py') try: - if (cache := grab_url_data(f'{UPSTREAM_URL}/{self.name}.py')): + if (cache := grab_url_data(f'{UPSTREAM_URL}/{self._path}.py')): self._cache = cache - return f'{UPSTREAM_URL}/{self.name}.py' + return f'{UPSTREAM_URL}/{self._path}.py' except urllib.error.HTTPError: pass @@ -85,7 +85,7 @@ class Profile(): else: raise ProfileError(f'Extension {os.path.splitext(absolute_path)[1]} is not a supported profile model. Only .py is supported.') - raise ProfileError(f'No such profile ({self.name}) was found either locally or in {UPSTREAM_URL}') + raise ProfileError(f'No such profile ({self._path}) was found either locally or in {UPSTREAM_URL}') def install(self): # To avoid profiles importing the wrong 'archinstall', @@ -102,98 +102,27 @@ class Profile(): # TODO: Remove __builtins__['installation'] = self.installer with instructions as runtime: - log(f'Profile {self.name} finished successfully.', bg='black', fg='green') - else: - if 'args' in instructions: - self.args = instructions['args'] - if 'post' in instructions: - instructions = instructions['post'] - - for title in instructions: - log(f'Running post installation step {title}') - - log('[N] Network Deploy: {}'.format(title)) - if type(instructions[title]) == str: - log('[N] Loading {} configuration'.format(instructions[title])) - log(f'Loading {instructions[title]} configuration') - instructions[title] = Application(self.installer, instructions[title], args=self.args) - instructions[title].install() - else: - for command in instructions[title]: - raw_command = command - opts = instructions[title][command] if type(instructions[title][command]) in (dict, OrderedDict) else {} - if len(opts): - if 'pass-args' in opts or 'format' in opts: - command = command.format(**self.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']) - - if 'pass-args' in opts and opts['pass-args']: - command = command.format(**self.args) - - if 'runas' in opts and f'su - {opts["runas"]} -c' not in command: - command = command.replace('"', '\\"') - command = f'su - {opts["runas"]} -c "{command}"' - - if 'no-chroot' in opts and opts['no-chroot']: - log(f'Executing {command} as simple command from live-cd.') - o = sys_command(command, opts) - elif 'chroot' in opts and opts['chroot']: - log(f'Executing {command} in 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 = sys_command(f"mount /dev/mapper/luksdev {self.installer.mountpoint}") - o = sys_command(f"cd {self.installer.mountpoint}; cp /etc/resolv.conf etc") - o = sys_command(f"cd {self.installer.mountpoint}; mount -t proc /proc proc") - o = sys_command(f"cd {self.installer.mountpoint}; mount --make-rslave --rbind /sys sys") - o = sys_command(f"cd {self.installer.mountpoint}; mount --make-rslave --rbind /dev dev") - o = sys_command(f'chroot {self.installer.mountpoint} /bin/bash -c "{command}"') - o = sys_command(f"cd {self.installer.mountpoint}; umount -R dev") - o = sys_command(f"cd {self.installer.mountpoint}; umount -R sys") - o = sys_command(f"cd {self.installer.mountpoint}; umount -R proc") - else: - if 'boot' in opts and opts['boot']: - log(f'Executing {command} in boot mode.') - defaults = { - 'login:' : 'root\n', - 'Password:' : self.args['password']+'\n', - f'[root@{self.args["hostname"]} ~]#' : command+'\n', - } - if not 'events' in opts: opts['events'] = {} - events = {**defaults, **opts['events']} - del(opts['events']) - o = b''.join(sys_command(f'/usr/bin/systemd-nspawn -D {self.installer.mountpoint} -b --machine temporary', events=events)) - else: - log(f'Executing {command} in with systemd-nspawn without boot.') - o = b''.join(sys_command(f'/usr/bin/systemd-nspawn -D {self.installer.mountpoint} --machine temporary {command}')) - if type(instructions[title][raw_command]) == bytes and len(instructions['post'][title][raw_command]) and not instructions['post'][title][raw_command] in o: - log(f'{command} failed: {o.decode("UTF-8")}') - log('[W] Post install command failed: {}'.format(o.decode('UTF-8'))) + log(f'Profile {self._path} finished successfully.', bg='black', fg='green') + return True class Application(Profile): def __repr__(self, *args, **kwargs): - return f'Application({self.name} <"{self.path}">)' + return f'Application({self._path} <"{self.path}">)' @property def path(self, *args, **kwargs): - if os.path.isfile(f'{self.name}'): - return os.path.abspath(f'{self.name}') + if os.path.isfile(f'{self._path}'): + return os.path.abspath(f'{self._path}') for path in ['./applications', './profiles/applications', '/etc/archinstall/applications', '/etc/archinstall/profiles/applications', os.path.abspath(f'{os.path.dirname(__file__)}/../profiles/applications')]: - if os.path.isfile(f'{path}/{self.name}.py'): - return os.path.abspath(f'{path}/{self.name}.py') + if os.path.isfile(f'{path}/{self._path}.py'): + return os.path.abspath(f'{path}/{self._path}.py') try: - if (cache := grab_url_data(f'{UPSTREAM_URL}/applications/{self.name}.py')): + if (cache := grab_url_data(f'{UPSTREAM_URL}/applications/{self._path}.py')): self._cache = cache - return f'{UPSTREAM_URL}/applications/{self.name}.py' + return f'{UPSTREAM_URL}/applications/{self._path}.py' except urllib.error.HTTPError: pass -- cgit v1.2.3-70-g09d2