diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2023-10-20 05:20:11 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2023-10-20 05:20:11 -0500 |
commit | a9ccd9bc7e22573c5c327d3f75722ebd3cca6a82 (patch) | |
tree | e2a5bfcdcad071b5045586673b32f9849b8b6991 | |
parent | 926aeb7fe8f50e5f1243b88a63d305c7d9f85371 (diff) | |
download | horizon-a9ccd9bc7e22573c5c327d3f75722ebd3cca6a82.tar.gz horizon-a9ccd9bc7e22573c5c327d3f75722ebd3cca6a82.tar.bz2 horizon-a9ccd9bc7e22573c5c327d3f75722ebd3cca6a82.tar.xz horizon-a9ccd9bc7e22573c5c327d3f75722ebd3cca6a82.zip |
hscript: Allow svcenable to create new runlevels
This is going to be useful in general for some advanced use cases, but
most importantly, it will allow us to define runlevels for live media.
Ref: #346
-rw-r--r-- | devel/requirements/3b_runner.xml | 8 | ||||
-rw-r--r-- | hscript/meta.cc | 12 | ||||
-rw-r--r-- | hscript/script_e.cc | 19 |
3 files changed, 37 insertions, 2 deletions
diff --git a/devel/requirements/3b_runner.xml b/devel/requirements/3b_runner.xml index a5080fe..b5e9848 100644 --- a/devel/requirements/3b_runner.xml +++ b/devel/requirements/3b_runner.xml @@ -820,6 +820,14 @@ <title>Runner.Execute.timezone.Missing</title> <para>If the zoneinfo file for the specified timezone in the <literal>timezone</literal> key is missing in the target namespace, but present in the installation environment, the system shall copy the zoneinfo file from the installation environment to the <literal>/etc/localtime</literal> file in the target namespace.</para> </formalpara> + <formalpara id="Runner.Execute.svcenable"> + <title>Runner.Execute.svcenable</title> + <para>The system shall configure the service manager in the target namespace to start services as specified in any specified <literal>svcenable</literal> keys.</para> + </formalpara> + <formalpara id="Runner.Execute.svcenable.AddlRunlevels"> + <title>Runner.Execute.svcenable.AddlRunlevels</title> + <para>If a runlevel not defined by the system service manager is specified in a <literal>svcenable</literal> key, it shall be interpreted to be a stacked runlevel atop the default runlevel and shall be configured as such in the target namespace.</para> + </formalpara> <formalpara id="Runner.Execute.bootloader"> <title>Runner.Execute.bootloader</title> <para>If a <literal>bootloader</literal> key is specified in the HorizonScript, the system shall perform the requested bootloader configuration.</para> diff --git a/hscript/meta.cc b/hscript/meta.cc index af72eaf..a12b874 100644 --- a/hscript/meta.cc +++ b/hscript/meta.cc @@ -652,12 +652,14 @@ bool SvcEnable::validate() const { /* LCOV_EXCL_STOP */ bool SvcEnable::execute() const { - const std::string target = script->targetDirectory() + - "/etc/runlevels/" + _runlevel + "/" + _svc; + const std::string target_rl = script->targetDirectory() + + "/etc/runlevels/" + _runlevel; + const std::string target = target_rl + "/" + _svc; const std::string initd = "/etc/init.d/" + _svc; output_info(pos, "svcenable: enabling service " + _svc); if(script->options().test(Simulate)) { + std::cout << "mkdir -p " << target_rl << std::endl; std::cout << "ln -s " << initd << " " << target << std::endl; return true; } @@ -667,6 +669,12 @@ bool SvcEnable::execute() const { if(!fs::exists(script->targetDirectory() + initd, ec)) { output_warning(pos, "svcenable: missing service", _svc); } + fs::create_directory(target_rl, ec); + if(ec && ec.value() != EEXIST) { + output_error(pos, "svcenable: could not create runlevel directory " + "/etc/runlevels/" + _runlevel, ec.message()); + return false; + } fs::create_symlink(initd, target, ec); if(ec && ec.value() != EEXIST) { diff --git a/hscript/script_e.cc b/hscript/script_e.cc index 3cdc78f..8f0f4b4 100644 --- a/hscript/script_e.cc +++ b/hscript/script_e.cc @@ -677,6 +677,25 @@ bool Script::execute() const { for(const auto &svc : internal->svcs_enable) { EXECUTE_OR_FAIL("svcenable", svc) } +#ifdef HAS_INSTALL_ENV + if(!opts.test(Simulate)) { + const std::set<std::string> def_runlevels{ + "boot", "default", "empty", "nonetwork", "shutdown", "sysinit" + }; + const auto rl_dir{targ_etc + "/runlevels"}; + for(auto &&file : fs::directory_iterator(rl_dir)) { + const auto runlevel{file.path().filename().string()}; + if(def_runlevels.find(runlevel) == def_runlevels.end()) { + fs::create_symlink("../default", + rl_dir + "/" + runlevel + "/default", ec); + if(ec) { + output_error("internal", "could not stack runlevel " + + runlevel, ec.message()); + } + } + } + } +#endif if(internal->boot) { EXECUTE_OR_FAIL("bootloader", internal->boot) |