Skip to content

Commit

Permalink
Merge pull request #5865 from BOINC/dpa_wsl_libc
Browse files Browse the repository at this point in the history
Extend support for WSL and Docker apps
  • Loading branch information
AenBleidd authored Oct 28, 2024
2 parents 592e9c4 + 63ef5f1 commit 96370db
Show file tree
Hide file tree
Showing 16 changed files with 182 additions and 61 deletions.
5 changes: 5 additions & 0 deletions client/client_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@ void CLIENT_STATE::show_host_info() {
"- OS: %s (%s)",
wsl.os_name.c_str(), wsl.os_version.c_str()
);
if (!wsl.libc_version.empty()) {
msg_printf(NULL, MSG_INFO,
"- libc version: %s", wsl.libc_version.c_str()
);
}
if (!wsl.docker_version.empty()) {
msg_printf(NULL, MSG_INFO, "- Docker version %s (%s)",
wsl.docker_version.c_str(),
Expand Down
22 changes: 9 additions & 13 deletions client/hostinfo_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1666,23 +1666,19 @@ int HOST_INFO::get_host_info(bool init) {
os_name, sizeof(os_name), os_version, sizeof(os_version)
);
#ifdef _WIN64
if (!cc_config.dont_use_wsl) {
OSVERSIONINFOEX osvi;
if (get_OSVERSIONINFO(osvi) && osvi.dwMajorVersion >= 10) {
retval = get_wsl_information(
cc_config.allowed_wsls, wsl_distros, !cc_config.dont_use_docker
OSVERSIONINFOEX osvi;
if (get_OSVERSIONINFO(osvi) && osvi.dwMajorVersion >= 10) {
retval = get_wsl_information(wsl_distros);
if (retval) {
msg_printf(0, MSG_INTERNAL_ERROR,
"get_wsl_information(): %s", boincerror(retval)
);
if (retval) {
msg_printf(0, MSG_INTERNAL_ERROR,
"get_wsl_information(): %s", boincerror(retval)
);
}
}
}
#endif
if (!cc_config.dont_use_vbox) {
get_virtualbox_version();
}

get_virtualbox_version();

get_processor_info(
p_vendor, sizeof(p_vendor),
p_model, sizeof(p_model),
Expand Down
47 changes: 26 additions & 21 deletions client/hostinfo_wsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ using std::string;
#include "str_replace.h"
#include "client_msgs.h"
#include "hostinfo.h"
#include "util.h"

// timeout for commands run in WSL container
// If something goes wrong we don't want client to hang
Expand Down Expand Up @@ -169,17 +170,12 @@ static bool got_both(WSL_DISTRO &wd) {
}

// Get list of WSL distros usable by BOINC
// (docker_desktop and those allowed by config)
// For each of them:
// try to find the OS name and version
// see if Docker and docker compose are present, get versions
// Return nonzero on error
//
int get_wsl_information(
vector<string> &allowed_wsls,
WSL_DISTROS &usable_distros,
bool detect_docker // whether to check for Docker
) {
int get_wsl_information(WSL_DISTROS &distros) {
WSL_DISTROS all_distros;
int retval = get_all_distros(all_distros);
if (retval) return retval;
Expand All @@ -199,14 +195,6 @@ int get_wsl_information(
if (wd.distro_name == "docker-desktop-data"){
continue;
}
// skip distros that are not allowed except for 'docker-desktop'
//
if (wd.distro_name != "docker-desktop"
&& std::find(allowed_wsls.begin(), allowed_wsls.end(), wd.distro_name) == allowed_wsls.end()
) {
msg_printf(0, MSG_INFO, "WSL distro '%s' detected but is not allowed", wd.distro_name.c_str());
continue;
}

char os_name[256];
char os_version[256];
Expand Down Expand Up @@ -314,20 +302,35 @@ int get_wsl_information(
// in case nothing worked
update_os(wd, "unknown", "unknown");

// get the libc version
if (!rs.run_program_in_wsl(
wd.distro_name, "ldd --version"
)) {
string buf;
read_from_pipe(rs.out_read, rs.proc_handle, buf, CMD_TIMEOUT);
wd.libc_version = parse_ldd_libc(buf.c_str());
}

// see if Docker is installed in the distro
//
if (detect_docker) {
get_docker_version(rs, wd);
get_docker_compose_version(rs, wd);
}
get_docker_version(rs, wd);
get_docker_compose_version(rs, wd);

usable_distros.distros.push_back(wd);
// see if distro is disallowed
//
vector<string> &dw = cc_config.disallowed_wsls;
if (std::find(dw.begin(), dw.end(), wd.distro_name) != dw.end()) {
wd.disallowed = true;
}
distros.distros.push_back(wd);
}

return 0;
}

static bool get_docker_version_aux(WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type) {
static bool get_docker_version_aux(
WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type
) {
bool ret = false;
string reply;
string cmd = string(docker_cli_prog(type)) + " --version";
Expand All @@ -349,7 +352,9 @@ static void get_docker_version(WSL_CMD &rs, WSL_DISTRO &wd) {
get_docker_version_aux(rs, wd, DOCKER);
}

static bool get_docker_compose_version_aux(WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type) {
static bool get_docker_compose_version_aux(
WSL_CMD &rs, WSL_DISTRO &wd, DOCKER_TYPE type
) {
bool ret = false;
string reply;
string cmd = string(docker_cli_prog(type)) + " compose version";
Expand Down
16 changes: 8 additions & 8 deletions client/log_flags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,17 @@ void CC_CONFIG::show() {
if (dont_use_vbox) {
msg_printf(NULL, MSG_INFO, "Config: don't use VirtualBox");
}
if (dont_use_docker) {
msg_printf(NULL, MSG_INFO, "Config: don't use Docker");
}
if (dont_use_wsl) {
msg_printf(NULL, MSG_INFO, "Config: don't use the Windows Subsystem for Linux");
msg_printf(NULL, MSG_INFO, "Config: don't use Windows Subsystem for Linux");
}
for (string s: allowed_wsls) {
for (string s: disallowed_wsls) {
msg_printf(NULL, MSG_INFO,
"Config: allowed WSL distro: %s", s.c_str()
"Config: disallowed WSL distro: %s", s.c_str()
);
}
if (dont_use_docker) {
msg_printf(NULL, MSG_INFO, "Config: don't use the Docker");
}
for (i=0; i<alt_platforms.size(); i++) {
msg_printf(NULL, MSG_INFO,
"Config: alternate platform: %s", alt_platforms[i].c_str()
Expand Down Expand Up @@ -381,8 +381,8 @@ int CC_CONFIG::parse_options_client(XML_PARSER& xp) {
if (xp.parse_bool("dont_suspend_nci", dont_suspend_nci)) continue;
if (xp.parse_bool("dont_use_vbox", dont_use_vbox)) continue;
if (xp.parse_bool("dont_use_wsl", dont_use_wsl)) continue;
if (xp.parse_string("allowed_wsl", s)) {
allowed_wsls.push_back(s);
if (xp.parse_string("disallowed_wsl", s)) {
disallowed_wsls.push_back(s);
continue;
}
if (xp.parse_bool("dont_use_docker", dont_use_docker)) continue;
Expand Down
12 changes: 6 additions & 6 deletions lib/cc_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ void CC_CONFIG::defaults() {
dont_suspend_nci = false;
dont_use_vbox = false;
dont_use_wsl = false;
allowed_wsls.clear();
disallowed_wsls.clear();
dont_use_docker = false;
exclude_gpus.clear();
exclusive_apps.clear();
Expand Down Expand Up @@ -351,8 +351,8 @@ int CC_CONFIG::parse_options(XML_PARSER& xp) {
if (xp.parse_bool("dont_use_vbox", dont_use_vbox)) continue;
if (xp.parse_bool("dont_use_docker", dont_use_docker)) continue;
if (xp.parse_bool("dont_use_wsl", dont_use_wsl)) continue;
if (xp.parse_string("allowed_wsl", s)) {
allowed_wsls.push_back(s);
if (xp.parse_string("disallowed_wsl", s)) {
disallowed_wsls.push_back(s);
continue;
}
if (xp.match_tag("exclude_gpu")) {
Expand Down Expand Up @@ -584,10 +584,10 @@ int CC_CONFIG::write(MIOFILE& out, LOG_FLAGS& log_flags) {
dont_use_docker
);

for (i=0; i<allowed_wsls.size(); ++i) {
for (i=0; i<disallowed_wsls.size(); ++i) {
out.printf(
" <allowed_wsl>%s</allowed_wsl>\n",
allowed_wsls[i].c_str()
" <disallowed_wsl>%s</disallowed_wsl>\n",
disallowed_wsls[i].c_str()
);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/cc_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ struct CC_CONFIG {
bool dont_suspend_nci;
bool dont_use_vbox;
bool dont_use_wsl;
std::vector<std::string> allowed_wsls;
std::vector<std::string> disallowed_wsls;
bool dont_use_docker;
std::vector<EXCLUDE_GPU> exclude_gpus;
std::vector<std::string> exclusive_apps;
Expand Down
6 changes: 1 addition & 5 deletions lib/hostinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,7 @@ class HOST_INFO {
extern void make_secure_random_string(char*);

#ifdef _WIN64
extern int get_wsl_information(
std::vector<std::string> &allowed_wsls,
WSL_DISTROS &usable_distros,
bool detect_docker
);
extern int get_wsl_information(WSL_DISTROS &distros);
extern int get_processor_group(HANDLE);
#endif

Expand Down
12 changes: 12 additions & 0 deletions lib/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,3 +686,15 @@ bool process_exists(int pid) {
}

#endif

string parse_ldd_libc(const char* input) {
char *q = (char*)strchr(input, '\n');
if (q) *q = 0;
const char *p = strrchr(input, ' ');
if (!p) return "";
int maj, min;
if (sscanf(p, "%d.%d", &maj, &min) != 2) return "";
string s = (string)p;
strip_whitespace(s);
return s;
}
7 changes: 7 additions & 0 deletions lib/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ extern int run_command(char *cmd, std::vector<std::string> &out);
//
extern int get_real_executable_path(char* path, size_t max_len);

// given a string of the form
// ldd (Ubuntu GLIBC 2.27-3ubuntu1.6) 2.27
// return "2.27" (or empty string if can't parse)
//

extern std::string parse_ldd_libc(const char* input);

#ifdef GCL_SIMULATOR
extern double simtime;
#define time(x) ((int)simtime)
Expand Down
37 changes: 33 additions & 4 deletions lib/wslinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ void WSL_DISTRO::clear() {
distro_name = "";
os_name = "";
os_version = "";
libc_version = "";
disallowed = false;
is_default = false;
wsl_version = 1;
wsl_version = 0;
docker_version = "";
docker_compose_version = "";
}
Expand All @@ -43,14 +45,28 @@ void WSL_DISTRO::write_xml(MIOFILE& f) {
" <distro_name>%s</distro_name>\n"
" <os_name>%s</os_name>\n"
" <os_version>%s</os_version>\n"
" <is_default>%d</is_default>\n"
" <wsl_version>%d</wsl_version>\n",
dn,
n,
v,
is_default ? 1 : 0,
wsl_version
);
if (is_default) {
f.printf(
" <is_default/>\n"
);
}
if (disallowed) {
f.printf(
" <disallowed/>\n"
);
}
if (!libc_version.empty()) {
f.printf(
" <libc_version>%s</libc_version>\n",
libc_version.c_str()
);
}
if (!docker_version.empty()) {
f.printf(
" <docker_version>%s</docker_version>\n"
Expand Down Expand Up @@ -82,7 +98,9 @@ int WSL_DISTRO::parse(XML_PARSER& xp) {
if (xp.parse_string("distro_name", distro_name)) continue;
if (xp.parse_string("os_name", os_name)) continue;
if (xp.parse_string("os_version", os_version)) continue;
if (xp.parse_string("libc_version", libc_version)) continue;
if (xp.parse_bool("is_default", is_default)) continue;
if (xp.parse_bool("disallowed", disallowed)) continue;
if (xp.parse_int("wsl_version", wsl_version)) continue;
if (xp.parse_string("docker_version", docker_version)) continue;
if (xp.parse_int("docker_type", i)) {
Expand All @@ -98,6 +116,13 @@ int WSL_DISTRO::parse(XML_PARSER& xp) {
return ERR_XML_PARSE;
}

int WSL_DISTRO::libc_version_int() {
int maj, min;
int n = sscanf(libc_version.c_str(), "%d.%d", &maj, &min);
if (n==2) return maj*100+min;
return 0;
}

WSL_DISTROS::WSL_DISTROS() {
clear();
}
Expand Down Expand Up @@ -131,7 +156,8 @@ int WSL_DISTROS::parse(XML_PARSER& xp) {
}

WSL_DISTRO* WSL_DISTROS::find_match(
const char *os_name_regexp, const char *os_version_regexp
const char *os_name_regexp, const char *os_version_regexp,
int min_libc_version
) {
std::regex name_regex(os_name_regexp), version_regex(os_version_regexp);
for (WSL_DISTRO &wd: distros) {
Expand All @@ -141,6 +167,9 @@ WSL_DISTRO* WSL_DISTROS::find_match(
if (!std::regex_match(wd.os_version.c_str(), version_regex)) {
continue;
}
if (wd.libc_version_int() < min_libc_version) {
continue;
}
return &wd;
}
return NULL;
Expand Down
8 changes: 7 additions & 1 deletion lib/wslinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ struct WSL_DISTRO {
// name of the operating system
std::string os_version;
// version of the operating system
std::string libc_version;
// version of libc, as reported by ldd --version
int wsl_version;
// version of WSL (currently 1 or 2)
bool is_default;
// this is the default distro
bool disallowed;
// disallowed in cc_config.xml
std::string docker_version;
// version of Docker (or podman)
// empty if not present
Expand All @@ -55,6 +59,7 @@ struct WSL_DISTRO {
void clear();
void write_xml(MIOFILE&);
int parse(XML_PARSER&);
int libc_version_int();
};

// a set of WSL distros
Expand All @@ -67,7 +72,8 @@ struct WSL_DISTROS {
void write_xml(MIOFILE&);
int parse(XML_PARSER&);
WSL_DISTRO *find_match(
const char *os_name_regexp, const char *os_version_regexp
const char *os_name_regexp, const char *os_version_regexp,
int min_libc_version
);
WSL_DISTRO *find_docker();
// find a distro containing Docker
Expand Down
Loading

0 comments on commit 96370db

Please sign in to comment.