Skip to content

Commit

Permalink
Tweaks to WSL and Docker support
Browse files Browse the repository at this point in the history
- New philosophy: always query the presence of software (WSL distros, Docker)
    even if client config doesn't allow its use.
    Send the config info to scheduler, and enforce it there.
- New philosophy: allow running jobs in any WSL distro
    except those disallowed in the config

- Add plan class support for WSL and Docker app versions

- client: query the libc version of WSL distros.
    The plan class entry for a WSL app version
    can specify a min libc version.

- wsl_wrapper: add --min_libc_version cmdline arg
    (should match plan class spec)

Notes:
encoding version numbers into integers (e.g. 2.27 -> 227) was a bad idea.
We should just store them as strings,
and define a VERSION_NUM class for parsing and comparing them.
Too late now, I guess
  • Loading branch information
davidpanderson committed Oct 28, 2024
1 parent dcb82a9 commit c11966b
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 54 deletions.
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
29 changes: 10 additions & 19 deletions client/hostinfo_wsl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,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 @@ -200,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 @@ -326,12 +313,16 @@ int get_wsl_information(

// 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()) {
dw.disallowed = true;
}
distros.distros.push_back(wd);
}

return 0;
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
29 changes: 25 additions & 4 deletions lib/wslinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ void WSL_DISTRO::clear() {
os_name = "";
os_version = "";
libc_version = "";
disallowed = false;
is_default = false;
wsl_version = 1;
wsl_version = 0;
docker_version = "";
docker_compose_version = "";
}
Expand All @@ -44,14 +45,22 @@ 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",
Expand Down Expand Up @@ -91,6 +100,7 @@ int WSL_DISTRO::parse(XML_PARSER& xp) {
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 @@ -106,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 @@ -139,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 @@ -149,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
6 changes: 5 additions & 1 deletion lib/wslinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct WSL_DISTRO {
// 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 @@ -57,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 @@ -69,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
7 changes: 6 additions & 1 deletion samples/wsl_wrapper/wsl_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,16 @@ void poll_client_msgs() {

int main(int argc, char** argv) {
const char *os_name_regexp=".*", *os_version_regexp=".*", *pass_thru="";
int min_libc_version = 0;
for (int i=1; i<argc; i++) {
if (!strcmp(argv[i], "--os_name_regexp")) {
os_name_regexp = argv[++i];
} else if (!strcmp(argv[i], "--os_version_regexp")) {
os_version_regexp = argv[++i];
} else if (!strcmp(argv[i], "--pass_thru")) {
pass_thru = argv[++i];
} else if (!strcmp(argv[i], "--min_libc_version")) {
min_libc_version = atoi(argv[++i]);
} else {
fprintf(stderr, "unknown option %s\n", argv[i]);
exit(1);
Expand All @@ -240,7 +243,9 @@ int main(int argc, char** argv) {
distro_name = "Ubuntu-22.04";
} else {
boinc_get_init_data(aid);
WSL_DISTRO *distro = aid.host_info.wsl_distros.find_match(os_name_regexp, os_version_regexp);
WSL_DISTRO *distro = aid.host_info.wsl_distros.find_match(
os_name_regexp, os_version_regexp, min_libc_version
);
if (!distro) {
fprintf(stderr, "can't find distro\n");
exit(1);
Expand Down
54 changes: 53 additions & 1 deletion sched/plan_class_spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,12 +546,64 @@ bool PLAN_CLASS_SPEC::check(
}

if (wsl) {
if (sreq.dont_use_wsl) {
add_no_work_message("Client config does not allow using WSL");
return false;
}
if (sreq.host.wsl_distros.distros.empty()) {
add_no_work_message("WSL is not available on this host");
add_no_work_message("No WSL distros found");
return false;
}
bool found = false;
for (WSL_DISTRO &wd: sreq.host.wsl_distros.distros) {
if (wd.disallowed) continue;
if (min_libc_version) {
if (wd.libc_version_int() < min_libc_version) continue;
}
found = true;
}
if (!found) {
add_no_work_message("No usable WSL distros found");
return false;
}
}

// Docker apps: check that:
// - Docker is allowed
// - Win:
// - WSL is allowed
// - There's an allowed WSL distro containing Docker
// - Unix:
// - Docker is present
if (docker) {
if (sreq.dont_use_docker) {
add_no_work_message("Client config does not allow using Docker");
return false;
}
if (strstr(sreq.host.os_name, "Windows")) {
if (sreq.dont_use_wsl) {
add_no_work_message("Client config does not allow using WSL");
return false;
}
bool found = false;
for (WSL_DISTRO &wd: sreq.host.wsl_distros.distros) {
if (wd.disallowed) continue;
if (wd.docker_version.empty()) continue;
found = true;
break;
}
if (!found) {
add_no_work_message("No usable WSL distros found");
return false;
}
} else {
if (strlen(sreq.host.docker_version) == 0) {
add_no_work_message("Docker not present");
return false;
}
}
}

// project-specific preference
//
if (have_project_prefs_regex && strlen(project_prefs_tag)) {
Expand Down
2 changes: 2 additions & 0 deletions sched/plan_class_spec.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct PLAN_CLASS_SPEC {
int min_android_version;
int max_android_version;
int min_libc_version;
// if WSL: applies to WSL distro
char project_prefs_tag[256];
bool have_project_prefs_regex;
regex_t project_prefs_regex;
Expand All @@ -64,6 +65,7 @@ struct PLAN_CLASS_SPEC {
// for non-compute-intensive, or override for GPU apps
bool have_host_summary_regex;
regex_t host_summary_regex;
// matched against host.serialnum
int user_id;
double infeasible_random;
long min_wu_id;
Expand Down
2 changes: 2 additions & 0 deletions sched/sched_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ void SCHEDULER_REQUEST::clear() {
strcpy(working_global_prefs_xml, "");
strcpy(code_sign_key, "");
dont_send_work = false;
dont_use_wsl = false;
dont_use_docker = false;
strcpy(client_brand, "");
global_prefs.defaults();
Expand Down Expand Up @@ -403,6 +404,7 @@ const char* SCHEDULER_REQUEST::parse(XML_PARSER& xp) {
if (xp.parse_double("duration_correction_factor", host.duration_correction_factor)) continue;
if (xp.parse_bool("dont_send_work", dont_send_work)) 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.match_tag("global_preferences")) {
safe_strcpy(global_prefs_xml, "<global_preferences>\n");
char buf[BLOB_SIZE];
Expand Down
Loading

0 comments on commit c11966b

Please sign in to comment.