localPackages.hpcstat: use exec from biu

This commit is contained in:
陈浩南 2024-06-10 18:34:40 +08:00
parent 7bd6e1f529
commit d8672ea42e
9 changed files with 47 additions and 83 deletions

View File

@ -18,6 +18,9 @@ namespace biu
else return value;
}
template <bool DirectStdout, bool DirectStderr>
detail_::ExecResult<DirectStdout, DirectStderr>::operator bool() const
{ return exit_code == 0; }
namespace detail_
{
template <ExecInput Input>

View File

@ -73,7 +73,7 @@ inputs: rec
{ src = inputs.topInputs.kylin-virtual-keyboard; };
biu = inputs.pkgs.callPackage ./biu { inherit nameof; };
zxorm = inputs.pkgs.callPackage ./zxorm { src = inputs.topInputs.zxorm; };
hpcstat = inputs.pkgs.callPackage ./hpcstat { inherit nameof sqlite-orm zpp-bits date openxlsx; };
hpcstat = inputs.pkgs.callPackage ./hpcstat { inherit nameof sqlite-orm zpp-bits date openxlsx biu; };
openxlsx = inputs.pkgs.callPackage ./openxlsx { src = inputs.topInputs.openxlsx; };
sqlite-orm = inputs.pkgs.callPackage ./sqlite-orm { src = inputs.topInputs.sqlite-orm; };
mkPnpmPackage = inputs.pkgs.callPackage ./mkPnpmPackage.nix {};

View File

@ -22,14 +22,15 @@ find_package(date REQUIRED)
find_package(OpenXLSX REQUIRED)
find_package(httplib REQUIRED)
find_package(termcolor REQUIRED)
find_package(biu REQUIRED)
add_executable(hpcstat src/main.cpp src/env.cpp src/keys.cpp src/ssh.cpp src/sql.cpp src/lfs.cpp src/common.cpp
src/push.cpp src/disk.cpp)
target_compile_features(hpcstat PUBLIC cxx_std_23)
target_compile_features(hpcstat PRIVATE cxx_std_23)
target_include_directories(hpcstat PRIVATE ${PROJECT_SOURCE_DIR}/include ${ZPP_BITS_INCLUDE_DIR})
target_link_libraries(hpcstat PRIVATE fmt::fmt Boost::headers Boost::filesystem sqlite_orm::sqlite_orm
nlohmann_json::nlohmann_json range-v3::range-v3 date::date date::date-tz OpenXLSX::OpenXLSX httplib::httplib
termcolor::termcolor)
termcolor::termcolor biu::biu)
target_compile_definitions(hpcstat PRIVATE HPCSTAT_VERSION="${HPCSTAT_VERSION}")
install(TARGETS hpcstat RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@ -1,13 +1,13 @@
{
stdenv, cmake, pkg-config, standalone ? false, version ? null, makeWrapper, lib,
boost, fmt, sqlite-orm, nlohmann_json, zpp-bits, range-v3, nameof, openssh, sqlite, date, openxlsx, httplib, openssl,
termcolor, duc
termcolor, duc, biu
}: stdenv.mkDerivation
{
name = "hpcstat";
src = ./.;
buildInputs =
[ boost fmt sqlite-orm nlohmann_json zpp-bits range-v3 nameof sqlite date openxlsx httplib termcolor openssl ];
[ boost fmt sqlite-orm nlohmann_json zpp-bits range-v3 nameof sqlite date openxlsx httplib termcolor openssl biu ];
nativeBuildInputs = [ cmake pkg-config makeWrapper ];
cmakeFlags = lib.optionals (version != null) [ "-DHPCSTAT_VERSION=${version}" ];
postInstall =

View File

@ -17,16 +17,11 @@
# include <date/tz.h>
# include <boost/interprocess/sync/file_lock.hpp>
# include <zpp_bits.h>
# include <biu.hpp>
namespace hpcstat
{
// run a program, wait until it exit, return its stdout if it return 0, otherwise nullopt
std::optional<std::string> exec
(
std::filesystem::path program, std::vector<std::string> args, std::optional<std::string> stdin = std::nullopt,
std::map<std::string, std::string> extra_env = {}
);
using namespace biu::literals;
// get current time
long now();

View File

@ -1,37 +1,9 @@
# include <hpcstat/common.hpp>
# include <hpcstat/sql.hpp>
# include <hpcstat/disk.hpp>
# include <boost/process.hpp>
namespace hpcstat
{
std::optional<std::string> exec
(
std::filesystem::path program, std::vector<std::string> args, std::optional<std::string> stdin,
std::map<std::string, std::string> extra_env
)
{
namespace bp = boost::process;
bp::ipstream output;
bp::opstream input;
std::unique_ptr<bp::child> process;
bp::environment env = boost::this_process::environment();
for (const auto& [key, value] : extra_env) env[key] = value;
if (stdin)
{
process = std::make_unique<bp::child>
(program.string(), bp::args(args), bp::std_out > output, bp::std_err > stderr, bp::std_in < input, env);
input << *stdin;
input.pipe().close();
}
else process = std::make_unique<bp::child>
(program.string(), bp::args(args), bp::std_out > output, bp::std_err > stderr, bp::std_in < bp::null, env);
process->wait();
if (process->exit_code() != 0) return std::nullopt;
std::stringstream ss;
ss << output.rdbuf();
return ss.str();
}
long now()
{
return std::chrono::duration_cast<std::chrono::seconds>

View File

@ -32,11 +32,11 @@ namespace hpcstat::disk
{ std::cerr << "HPCSTAT_DATADIR not set\n"; return false; }
else if
(
auto result = exec
auto result = biu::exec
(
// duc index -d ./duc.db -p ~
fmt::format("{}/duc", *ducbindir),
{ "index", "-d", fmt::format("{}/duc.db", *datadir), "-p", *homedir }
"{}/duc"_f(*ducbindir),
{ "index", "-d", "{}/duc.db"_f(*datadir), "-p", *homedir }
);
!result
)
@ -56,13 +56,13 @@ namespace hpcstat::disk
{
if
(
auto result = exec
auto result = biu::exec
(
// duc ls -d ./duc.db -b -D /data/gpfs01/jykang/linwei/xxx
fmt::format("{}/duc", *ducbindir),
"{}/duc"_f(*ducbindir),
{
"ls", "-d", fmt::format("{}/duc.db", *datadir), "-b", "-D",
fmt::format("{}{}{}", *homedir, path ? "/" : "", path.value_or(""))
"ls", "-d", "{}/duc.db"_f(*datadir), "-b", "-D",
"{}{}{}"_f(*homedir, path ? "/" : "", path.value_or(""))
}
);
!result
@ -71,8 +71,8 @@ namespace hpcstat::disk
else
{
std::smatch match;
if (!std::regex_search(*result, match, std::regex(R"((\d+))")))
{ std::cerr << fmt::format("failed to parse {}\n", *result); return std::nullopt; }
if (!std::regex_search(result.std_out, match, std::regex(R"((\d+))")))
{ std::cerr << fmt::format("failed to parse {}\n", result.std_out); return std::nullopt; }
return std::stod(match[1]) / 1024 / 1024 / 1024;
}
};
@ -88,11 +88,9 @@ namespace hpcstat::disk
{
if
(
auto result = exec
(
// duc info -d ./duc.db
fmt::format("{}/duc", *ducbindir),
{ "info", "-d", fmt::format("{}/duc.db", *datadir) });
// duc info -d ./duc.db
auto result = biu::exec
("{}/duc"_f(*ducbindir), { "info", "-d", "{}/duc.db"_f(*datadir) });
!result
)
{ std::cerr << fmt::format("failed to get duc info\n"); return {}; }
@ -100,8 +98,8 @@ namespace hpcstat::disk
{
std::smatch match;
// search string like 2024-06-08 13:45:19
if (!std::regex_search(*result, match, std::regex(R"((\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}))")))
{ std::cerr << fmt::format("failed to parse {}\n", *result); return {}; }
if (!std::regex_search(result.std_out, match, std::regex(R"((\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}))")))
{ std::cerr << fmt::format("failed to parse {}\n", result.std_out); return {}; }
return match[1];
}
};

View File

@ -1,6 +1,5 @@
# include <hpcstat/lfs.hpp>
# include <hpcstat/env.hpp>
# include <boost/process.hpp>
# include <nlohmann/json.hpp>
namespace hpcstat::lfs
@ -28,17 +27,17 @@ namespace hpcstat::lfs
}
else break;
}
if (auto result = exec(*bsub, args); !result) return std::nullopt;
if (auto result = biu::exec(*bsub, args); !result) return std::nullopt;
else
{
// Job <462270> is submitted to queue <normal_1day>.
std::regex re(R"r(Job <(\d+)> is submitted to queue <(\w+)>.)r");
std::smatch match;
if (std::regex_search(*result, match, re))
if (std::regex_search(result.std_out, match, re))
return std::make_pair(std::stoi(match[1]), match[2]);
else
{
std::cerr << fmt::format("Failed to parse job id from output: {}\n", *result);
std::cerr << fmt::format("Failed to parse job id from output: {}\n", result.std_out);
return std::nullopt;
}
}
@ -49,11 +48,10 @@ namespace hpcstat::lfs
{
if
(
auto result = exec
auto result = biu::exec<{.SearchPath = true}>
(
boost::process::search_path("bjobs").string(),
{ "-a", "-o", "jobid submit_time stat cpu_used job_name", "-json" },
std::nullopt, { { "LSB_DISPLAY_YEAR", "Y" } }
"bjobs", { "-a", "-o", "jobid submit_time stat cpu_used job_name", "-json" },
{}, { { "LSB_DISPLAY_YEAR", "Y" } }
);
!result
)
@ -61,7 +59,7 @@ namespace hpcstat::lfs
else
{
nlohmann::json j;
try { j = nlohmann::json::parse(*result); }
try { j = nlohmann::json::parse(result.std_out); }
catch (nlohmann::json::parse_error& e)
{
std::cerr << fmt::format("Failed to parse bjobs output: {}\n", e.what());
@ -90,14 +88,11 @@ namespace hpcstat::lfs
{
if
(
auto result = exec
(
boost::process::search_path("bjobs").string(),
{ "-l", std::to_string(jobid) }
);
auto result = biu::exec<{.SearchPath = true}>
("bjobs", { "-l", std::to_string(jobid) });
!result
)
return std::nullopt;
else return *result;
else return result.std_out;
}
}

View File

@ -2,7 +2,6 @@
# include <hpcstat/keys.hpp>
# include <hpcstat/env.hpp>
# include <boost/filesystem.hpp>
# include <boost/process.hpp>
# include <boost/dll.hpp>
namespace hpcstat::ssh
@ -13,8 +12,7 @@ namespace hpcstat::ssh
return std::nullopt;
else if
(
auto output =
exec(std::filesystem::path(*sshbindir) / "ssh-add", { "-l" });
auto output = biu::exec(std::filesystem::path(*sshbindir) / "ssh-add", { "-l" });
!output
)
{ std::cerr << "Failed to get ssh fingerprints\n"; return std::nullopt; }
@ -24,11 +22,13 @@ namespace hpcstat::ssh
std::smatch match;
for
(
auto i = std::sregex_iterator(output->begin(), output->end(), pattern);
i != std::sregex_iterator(); ++i
auto i = std::sregex_iterator
(output.std_out.begin(), output.std_out.end(), pattern);
i != std::sregex_iterator();
++i
)
if (Keys.contains(i->str(1))) return i->str(1);
std::cerr << fmt::format("No valid fingerprint found in:\n{}\n", *output);
std::cerr << fmt::format("No valid fingerprint found in:\n{}\n", output.std_out);
return std::nullopt;
}
}
@ -40,12 +40,12 @@ namespace hpcstat::ssh
return std::nullopt;
else if
(
auto output = exec
auto output = biu::exec
(
std::filesystem::path(*sshbindir) / "ssh-keygen",
{
"-Y", "sign", "-q",
"-f", fmt::format("{}/keys/{}", *sharedir, Keys[fingerprint].PubkeyFilename),
"-f", "{}/keys/{}"_f(*sharedir, Keys[fingerprint].PubkeyFilename),
"-n", "hpcstat@chn.moe", "-"
},
message
@ -53,7 +53,7 @@ namespace hpcstat::ssh
!output
)
{ std::cerr << fmt::format("Failed to sign message: {}\n", message); return std::nullopt; }
else return *output;
else return output.std_out;
}
bool verify(std::string message, std::string signature, std::string fingerprint)
{
@ -68,18 +68,18 @@ namespace hpcstat::ssh
bf::create_directories(tempdir);
auto signaturefile = tempdir / "signature";
std::ofstream(signaturefile) << signature;
auto result = exec
auto result = biu::exec
(
std::filesystem::path(*sshbindir) / "ssh-keygen",
{
"-Y", "verify",
"-f", fmt::format("{}/keys/{}", *sharedir, Keys[fingerprint].PubkeyFilename),
"-f", "{}/keys/{}"_f(*sharedir, Keys[fingerprint].PubkeyFilename),
"-n", "hpcstat@chn.moe", "-s", signaturefile.string()
},
message
);
std::filesystem::remove_all(tempdir.string());
return result.has_value();
return result;
}
}
}