From 681481cec01c3ed15c64dce4b0880dd753e3d882 Mon Sep 17 00:00:00 2001 From: wanchao-xu Date: Fri, 5 Jul 2024 15:52:50 +0800 Subject: [PATCH] Add new section 'runscript_out_bootstrap' for kickstart to run script on host pc after image created. Change-Id: Iddc432572cb7826b4e604439b889c737e6a87006 Signed-off-by: wanchao-xu --- mic/3rdparty/pykickstart/constants.py | 1 + mic/3rdparty/pykickstart/parser.py | 1 + mic/3rdparty/pykickstart/sections.py | 7 ++++++ mic/kickstart/__init__.py | 8 +++++++ mic/rt_util.py | 44 ++++++++++++++++++++++++++++++++++- tools/mic | 2 +- 6 files changed, 61 insertions(+), 2 deletions(-) diff --git a/mic/3rdparty/pykickstart/constants.py b/mic/3rdparty/pykickstart/constants.py index 050d124..9266872 100644 --- a/mic/3rdparty/pykickstart/constants.py +++ b/mic/3rdparty/pykickstart/constants.py @@ -41,6 +41,7 @@ KS_SCRIPT_POST = 1 KS_SCRIPT_TRACEBACK = 2 KS_SCRIPT_RUN = 3 KS_SCRIPT_UMOUNT = 4 +KS_SCRIPT_RUN_OUT_BOOTSTRAP = 5 KS_WAIT = 0 KS_REBOOT = 1 diff --git a/mic/3rdparty/pykickstart/parser.py b/mic/3rdparty/pykickstart/parser.py index a485dfe..ec4f3f0 100644 --- a/mic/3rdparty/pykickstart/parser.py +++ b/mic/3rdparty/pykickstart/parser.py @@ -723,6 +723,7 @@ class KickstartParser: self.registerSection(TracebackScriptSection(self.handler, dataObj=Script)) self.registerSection(RunScriptSection(self.handler, dataObj=Script)) self.registerSection(PostUmountScriptSection(self.handler, dataObj=Script)) + self.registerSection(RunScriptOutBootstrapSection(self.handler, dataObj=Script)) self.registerSection(PackageSection(self.handler)) self.registerSection(TpkPackageSection(self.handler)) diff --git a/mic/3rdparty/pykickstart/sections.py b/mic/3rdparty/pykickstart/sections.py index c360a90..26bafbc 100644 --- a/mic/3rdparty/pykickstart/sections.py +++ b/mic/3rdparty/pykickstart/sections.py @@ -225,6 +225,13 @@ class PostUmountScriptSection(ScriptSection): raise KickstartError("%runscript and %post-umount " \ "can not be defined together") +class RunScriptOutBootstrapSection(ScriptSection): + sectionOpen = "%runscript_out_bootstrap" + + def _resetScript(self): + ScriptSection._resetScript(self) + self._script["type"] = KS_SCRIPT_RUN_OUT_BOOTSTRAP + class PackageSection(Section): sectionOpen = "%packages" diff --git a/mic/kickstart/__init__.py b/mic/kickstart/__init__.py index 46bcca2..2691a9d 100755 --- a/mic/kickstart/__init__.py +++ b/mic/kickstart/__init__.py @@ -886,6 +886,14 @@ def get_sign_scripts(ks): scripts.append(s) return scripts +def get_out_bootstarp_scripts(ks): + scripts = [] + for s in ks.handler.scripts: + if s.type != ksparser.KS_SCRIPT_RUN_OUT_BOOTSTRAP: + continue + scripts.append(s) + return scripts + def add_repo(ks, repostr): args = repostr.split() repoobj = ks.handler.repo.parse(args[1:]) diff --git a/mic/rt_util.py b/mic/rt_util.py index b79e800..5ae765b 100644 --- a/mic/rt_util.py +++ b/mic/rt_util.py @@ -21,9 +21,10 @@ import glob import re import shutil import subprocess +import tempfile import ctypes -from mic import bootstrap, msger +from mic import bootstrap, msger, kickstart from mic.conf import configmgr from mic.utils import errors, proxy from mic.utils.fs_related import find_binary_path, makedirs @@ -64,6 +65,45 @@ def inbootstrap(): return True return (os.stat("/").st_ino != 2) +# Provide '%runscript_out_bootstrap' section for kickstart, and runscript_out_bootstrap can +# be run on local PC after image created. The default interpreter is /bin/sh, +# use '--interpreter' to specify interpreter ('%runscript_out_bootstrap --interpreter=/bin/bash') +def run_scripts_out_bootstrap(ks, rundir, env=None): + if kickstart.get_out_bootstarp_scripts(ks)==[]: + return + + msger.info("Running scripts out bootstrap ...") + for s in kickstart.get_out_bootstarp_scripts(ks): + (fd, path) = tempfile.mkstemp(prefix = "ks-runscript-out-bootstrap-") + s.script = s.script.replace("\r", "") + os.write(fd, s.script) + if s.interp == '/bin/sh' or s.interp == '/bin/bash': + os.write(fd, '\n') + os.write(fd, 'exit 0\n') + os.close(fd) + os.chmod(path, 0o700) + + oldoutdir = os.getcwd() + if os.path.exists(rundir): + os.chdir(rundir) + try: + try: + p = subprocess.Popen([s.interp, path], + env = env, + stdout = subprocess.PIPE, + stderr = subprocess.STDOUT) + while p.poll() == None: + msger.info(p.stdout.readline().strip()) + if p.returncode != 0: + raise errors.CreatorError("Failed to execute script out bootstrap " + "with '%s'" % (s.interp)) + except OSError as msg: + raise errors.CreatorError("Failed to execute script out bootstrap " + "with '%s' : %s" % (s.interp, msg)) + finally: + os.chdir(oldoutdir) + os.unlink(path) + def bootstrap_mic(argv=None): def mychroot(): os.chroot(rootdir) @@ -128,6 +168,8 @@ def bootstrap_mic(argv=None): value,tb = sys.exc_info()[1:] raise errors.CreatorError((value,tb)) else: + if not ret: + run_scripts_out_bootstrap(cropts['ks'], cropts['outdir']) sys.exit(ret) finally: bsenv.cleanup() diff --git a/tools/mic b/tools/mic index 42b316b..0e3947e 100755 --- a/tools/mic +++ b/tools/mic @@ -138,7 +138,7 @@ def create_parser(parser): dest='interactive', default=True, help='interactive output') parent_parser.add_argument('--run_script', action='store', dest='run_script', - default=None, help='Run script on local PC after image created') + default=None, help='Run script on mic bootstrap after image created') parent_parser.add_argument('--tpk_install', action='store', dest='tpk_install', default=None, help='Copy tpk file to /usr/apps/.preload-tpk') parent_parser.add_argument('--rpm-debug', action='store_true', dest='rpm_debug', help='Set debug mode for rpm install') -- 2.7.4