Control: tags -1 patch thanks On Wed, Aug 19, 2020 at 02:46:47PM +0200, Marc Haber wrote: > Please consider adding this as a feature. Unfortunately, I am not fluent > enough in python to deliver a patch.
This has changed in the four years that this issue has rotted around in the BTS. Please find attached a small patch that introduces an extensible hook mechanism. At the moment, the hook script is only called at the create stage, which allows me to solve the pressing issue at hand (enable two foreign architectures inside the container). A possible hook script is: #!/usr/bin/python3 import argparse import subprocess import sys def create(): subprocess.run(["dpkg", "--add-architecture", "armhf"], check=True) subprocess.run(["dpkg", "--add-architecture", "arm64"], check=True) subprocess.run(["apt", "update"], check=True) print("System architecture added and package list updated.") def main(): parser = argparse.ArgumentParser( description="Setup system architecture and update package list." ) parser.add_argument("command", help="Command to execute (e.g., 'create')") args = parser.parse_args() if args.command == "create": create() else: print(f"Unknown command: {args.command}") sys.exit(1) if __name__ == "__main__": main() Greetigns Marc
diff --git a/debspawn/cli.py b/debspawn/cli.py index d7fe299..90e97bf 100644 --- a/debspawn/cli.py +++ b/debspawn/cli.py @@ -100,6 +100,7 @@ def command_create(options): variant=options.variant, base_suite=options.base_suite, custom_name=options.name, + hook_path=options.hook_path, ) r = osbase.create( options.mirror, @@ -450,6 +451,12 @@ def create_parser(formatter_class=None): dest='with_init', help='Include an init system in this image, so it is bootable.', ) + sp.add_argument( + '--hook-path', + action='store', + dest='hook_path', + help='Path to hook script', + ) sp.set_defaults(func=command_create) # 'delete' command diff --git a/debspawn/dsrun b/debspawn/dsrun index 8d6618d..d47d09c 100755 --- a/debspawn/dsrun +++ b/debspawn/dsrun @@ -357,6 +357,23 @@ def run_qatasks(qa_lintian=True): return True +def run_hook(step): + ''' Run hook script''' + hook_path = "/usr/lib/debspawn/hook" + if not os.path.isfile(hook_path): + print('ERROR: No hook script here in container') + sys.exit(2) + + cmd = [hook_path, + step, + ] + run_command(cmd) + + # run_command will exit the whole program if the command failed, + # so we can return True here (everything went fine if we are here) + return True + + def setup_environment(builder_uid=None, use_color=True, use_unicode=True, *, is_update=False): os.environ['LANG'] = 'C.UTF-8' if use_unicode else 'C' os.environ['LC_ALL'] = 'C.UTF-8' if use_unicode else 'C' @@ -414,6 +431,8 @@ def main(): help='Prepare container image for generic script run.') parser.add_argument('--run-qa', action='store_true', dest='run_qatasks', help='Run QA tasks (only Lintian currently) against a package.') + parser.add_argument('--run-hook-create', action='store_true', dest='run_hook_create', + help='Run Hook Script after creating container.') options = parser.parse_args(sys.argv[1:]) @@ -449,6 +468,10 @@ def main(): r = run_qatasks(qa_lintian=options.qa_lintian) if not r: return 2 + elif options.run_hook_create: + r = run_hook("create") + if not r: + return 2 else: print('ERROR: No action specified.', file=sys.stderr) return 1 diff --git a/debspawn/osbase.py b/debspawn/osbase.py index 3df261d..ca0044f 100644 --- a/debspawn/osbase.py +++ b/debspawn/osbase.py @@ -73,6 +73,7 @@ class OSBase: base_suite=None, custom_name=None, cachekey=None, + hook_path=None, ): self._gconf = gconf self._suite = suite @@ -91,6 +92,7 @@ class OSBase: self._cachekey = cachekey if self._cachekey: self._cachekey = self._cachekey.replace(' ', '') + self.hook_path = hook_path self._parameters_checked = False self._aptcache = APTCache(self) @@ -228,17 +230,23 @@ class OSBase: self._results_dir = path Path(self._results_dir).mkdir(exist_ok=True) - def _copy_helper_script(self, osroot_path): + def _copy_script(self, source_path, osroot_path, targetfname): script_location = os.path.join(osroot_path, 'usr', 'lib', 'debspawn') Path(script_location).mkdir(parents=True, exist_ok=True) - script_fname = os.path.join(script_location, 'dsrun') + script_fname = os.path.join(script_location, targetfname) if os.path.isfile(script_fname): os.remove(script_fname) - shutil.copy2(self._gconf.dsrun_path, script_fname) + shutil.copy2(source_path, script_fname) os.chmod(script_fname, 0o0755) + def _copy_helper_script(self, osroot_path): + self._copy_script(self._gconf.dsrun_path, osroot_path, 'dsrun') + + def _copy_hook_script(self, osroot_path): + self._copy_script(self.hook_path, osroot_path, 'hook') + def get_image_location(self): return os.path.join(self._gconf.osroots_dir, '{}.tar.zst'.format(self.name)) @@ -494,6 +502,8 @@ class OSBase: print('Variant: {}'.format(self.variant)) if with_init: print('Includes init: yes') + if self.hook_path: + print('Hook Script: {}'.format(self.hook_path)) include_pkgs = ['passwd', 'python3-minimal', 'eatmydata'] if with_init: @@ -527,6 +537,10 @@ class OSBase: # create helper script runner self._copy_helper_script(tdir) + # copy hook script + if self.hook_path: + self._copy_hook_script(tdir) + # if we bootstrapped the base suite, add the primary suite to # sources.list. We also add any explicit extra suites and source lines if self.has_base_suite or extra_suites or extra_source_lines: @@ -634,6 +648,16 @@ class OSBase: ): return False + if self.hook_path: + print_section('Run Hook Create') + if ( + nspawn_run_helper_persist( + self, tdir, self.new_nspawn_machine_name(), '--run-hook-create', build_uid=0, + ) + != 0 + ): + return False + # drop any unwanted files (again) before building the tarball self._remove_unwanted_files(tdir)