packages.info: finish

This commit is contained in:
2025-02-02 23:20:14 +08:00
parent f195c05031
commit 550250fa83

View File

@@ -7,36 +7,41 @@ extern "C"
# include <slurm/spank.h>
# include <slurm/slurm.h>
// ac argv: configuration count and flags in plugstack.conf
[[gnu::visibility("default")]] int slurm_spank_exit(spank_t spank, int ac, char** argv);
[[gnu::visibility("default")]] int slurm_spank_job_epilog(spank_t spank, int ac, char** argv);
}
struct switch_user
{
std::uint32_t uid, gid;
switch_user(std::uint32_t uid, std::uint32_t gid) : uid(uid), gid(gid) {}
boost::system::error_code on_exec_setup(auto&&...)
{
// first set gid then set uid, otherwise failed
if (setegid(1000) != 0 || seteuid(1000) != 0)
if (setegid(gid) != 0 || seteuid(uid) != 0)
return boost::system::error_code{errno, boost::system::system_category()};
else return {};
return {};
}
};
int slurm_spank_exit(spank_t spank, int ac, char** argv)
int slurm_spank_job_epilog(spank_t spank, int ac, char** argv)
{
using namespace biu::literals;
if (spank_context() == S_CTX_REMOTE)
auto [info, outfile, uid, gid] = [&]
{
std::stringstream ss;
std::optional<std::string> outfile;
ss << "------------------------------------------------------------\n";
std::uint32_t jid;
std::uint32_t jid, uid = -1, gid = -1;
auto result = spank_get_item(spank, S_JOB_ID, &jid);
if (result != ESPANK_SUCCESS) ss << "error getting job id: {}\n"_f(int(result));
else
{
ss << "info for job {}:\n"_f(jid);
YAML::Node info;
// gather info from slurmctld
job_info_msg_t* job_info;
// slurm_init(nullptr);
slurm_init(nullptr);
auto result = slurm_load_job(&job_info, jid, 0);
if (result != SLURM_SUCCESS) ss << "error loading job info: {}\n"_f(slurm_strerror(result));
else if (job_info->record_count != 1) ss << "record_count {} != 1\n"_f(job_info->record_count);
@@ -47,11 +52,13 @@ int slurm_spank_exit(spank_t spank, int ac, char** argv)
{ return "{:%Y-%m-%d %H:%M:%S}"_f(*std::localtime(&time)); };
auto timespan = [](time_t time)
{ return "{:%H:%M:%S}"_f(std::chrono::seconds(time)); };
YAML::Node info;
auto get_status = [](int code)
{ return std::vector{ "{}"_f(job_states(code & 0xff)), "{:#x}"_f(code) }; };
info["Job Id"] = job_info->job_array->job_id;
info["Job Name"] = null_to_empty(job_info->job_array->name);
info["User Id"] = job_info->job_array->user_id;
info["Work Directory"] = null_to_empty(job_info->job_array->work_dir);
info["Output File"] = null_to_empty(job_info->job_array->std_out);
info["Partition"] = null_to_empty(job_info->job_array->partition);
info["Submit Time"] = timepoint(job_info->job_array->submit_time);
info["Start Time"] = timepoint(job_info->job_array->start_time);
@@ -59,23 +66,38 @@ int slurm_spank_exit(spank_t spank, int ac, char** argv)
info["Nodes"] = null_to_empty(job_info->job_array->nodes);
info["TREs Allocated"] = null_to_empty(job_info->job_array->tres_alloc_str);
info["GREs Allocated"] = null_to_empty(job_info->job_array->gres_total);
info["Status"] = job_info->job_array->job_state;
ss << "------------------------------------------------------------\n" << info;
info["Status"] = get_status(job_info->job_array->job_state);
if (job_info->job_array->std_out != nullptr) outfile = job_info->job_array->std_out;
uid = job_info->job_array->user_id;
gid = job_info->job_array->group_id;
}
slurm_free_job_info_msg(job_info);
slurm_fini();
ss << "------------------------------------------------------------\n" << info << '\n';
}
return std::tuple(ss.str(), outfile, uid, gid);
}();
slurm_spank_log("%s", info.c_str());
if (outfile)
{
try
{
boost::asio::io_context context;
boost::system::error_code ec;
boost::asio::readable_pipe rp{context};
boost::process::v2::process proc(context, "/run/current-system/sw/bin/capsh", { "--print" }, boost::process::v2::process_stdio{nullptr, rp, nullptr}, switch_user{});
std::string output;
boost::asio::read(rp, boost::asio::dynamic_buffer(output), ec);
if (ec != boost::asio::error::eof) ss << "error reading whoami: {}\n"_f(ec.message());
ss << "\nusername: {}"_f(output);
boost::asio::writable_pipe wp{context};
boost::process::v2::process proc
(
context, "/run/current-system/sw/bin/tee", { "-a", outfile->c_str() },
boost::process::v2::process_stdio{wp, nullptr, nullptr}, switch_user(uid, gid)
);
boost::asio::write(wp, boost::asio::buffer(info));
wp.close();
proc.wait();
}
slurm_spank_log("%s", ss.str().c_str());
catch (boost::system::system_error& e) { slurm_spank_log("boost error writing to output file: %s", e.what()); }
catch (std::exception& e) { slurm_spank_log("error writing to output file: %s", e.what()); }
catch (...) { slurm_spank_log("error writing to output file"); }
}
return 0;
}