From 92e7ed642f3980c09b4ccc19b76904362413359a Mon Sep 17 00:00:00 2001 From: Vitalii Koshura Date: Fri, 16 Aug 2024 17:31:11 +0200 Subject: [PATCH 1/2] [sched] add docker plan class spec Co-authored-by: Tanya1515 Signed-off-by: Vitalii Koshura --- sched/plan_class_spec.cpp | 130 ++++++++++++++++++++++++++++++- sched/plan_class_spec.h | 8 +- sched/plan_class_spec.xml.sample | 12 +++ sched/sched_customize.cpp | 24 +++++- 4 files changed, 168 insertions(+), 6 deletions(-) diff --git a/sched/plan_class_spec.cpp b/sched/plan_class_spec.cpp index bfeb852cdcc..3234f17a8f0 100644 --- a/sched/plan_class_spec.cpp +++ b/sched/plan_class_spec.cpp @@ -1,6 +1,6 @@ // This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2023 University of California +// https://boinc.berkeley.edu +// Copyright (C) 2024 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License @@ -455,6 +455,124 @@ bool PLAN_CLASS_SPEC::check( return false; } + if (docker){ + if (!(sreq.host.docker_available)) { + add_no_work_message("Docker is not installed or is not available"); + return false; + } + + if (docker_compose && !(sreq.host.docker_compose_available)) { + add_no_work_message("Docker compose is not installed or is not available"); + return false; + } + if (sreq.host.wsl_available) { + bool docker_found = false; + bool docker_compose_found = false; + for (int i = 0; i < sreq.host.wsls.wsls.size(); i++) { + if (sreq.host.wsls.wsls[i].is_docker_available) { + if (docker_compose && sreq.host.wsls.wsls[i].is_docker_compose_available) { + int maj, min, rel; + int n = sscanf(sreq.host.wsls.wsls[i].docker_version.c_str(), "%d.%d.%d", &maj, &min, &rel); + if (n != 3) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: can't parse docker version\n" + ); + continue; + } + } + int v = maj*10000 + min*100 + rel; + if (min_docker_version && v < min_docker_version) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: docker version too low: %d < %d\n", + v, min_docker_version + ); + continue; + } + } + docker_found = true; + } + if (!docker_compose && docker_found) { + break; + } + } + if (docker_compose && sreq.host.wsls.wsls[i].is_docker_compose_available) { + int maj, min, rel; + int n = sscanf(sreq.host.wsls.wsls[i].docker_compose_version.c_str(), "%d.%d.%d", &maj, &min, &rel); + if (n != 3) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: can't parse docker compose version\n" + ); + continue; + } + } + int v = maj*10000 + min*100 + rel; + if (min_docker_compose_version && v < min_docker_compose_version) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: docker compose version too low: %d < %d\n", + v, min_docker_compose_version + ); + continue; + } + } + docker_compose_found = true; + } + } + if (!docker_found) { + add_no_work_message("Suitable Docker is not installed or is not available"); + return false; + } + if (docker_compose && !docker_compose_found) { + add_no_work_message("Suitable Docker compose is not installed or is not available"); + return false; + } + } else { + int maj, min, rel; + int n = sscanf(sreq.host.docker_version, "%d.%d.%d", &maj, &min, &rel); + if (n != 3) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: can't parse docker version\n" + ); + } + return false; + } + int v = maj*10000 + min*100 + rel; + if (min_docker_version && v < min_docker_version) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: docker version too low: %d < %d\n", + v, min_docker_version + ); + } + return false; + } + + n = sscanf(sreq.host.docker_compose_version, "%d.%d.%d", &maj, &min, &rel); + if (n != 3) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: can't parse docker compose version\n" + ); + } + return false; + } + v = maj*10000 + min*100 + rel; + if (min_docker_compose_version && v < min_docker_compose_version) { + if (config.debug_version_select) { + log_messages.printf(MSG_NORMAL, + "[version] plan_class_spec: docker compose version too low: %d < %d\n", + v, min_docker_compose_version + ); + } + return false; + } + } + } + if (virtualbox) { // host must run 7.0+ client @@ -1099,6 +1217,10 @@ int PLAN_CLASS_SPEC::parse(XML_PARSER& xp) { if (xp.parse_bool("cal", cal)) continue; if (xp.parse_bool("opencl", opencl)) continue; if (xp.parse_bool("virtualbox", virtualbox)) continue; + if (xp.parse_bool("docker", docker)) continue; + if (xp.parse_bool("docker_compose", docker_compose)) continue; + if (xp.parse_int("min_docker_version", min_docker_version)) continue; + if (xp.parse_int("min_docker_compose_version", min_docker_compose_version)) continue; if (xp.parse_bool("is64bit", is64bit)) continue; if (xp.parse_str("cpu_feature", buf, sizeof(buf))) { cpu_features.push_back(" " + (string)buf + " "); @@ -1245,6 +1367,10 @@ PLAN_CLASS_SPEC::PLAN_CLASS_SPEC() { cal = false; opencl = false; virtualbox = false; + docker = false; + docker_compose = false; + min_docker_version = 0; + min_docker_compose_version = 0; is64bit = false; min_ncpus = 0; max_threads = 1; diff --git a/sched/plan_class_spec.h b/sched/plan_class_spec.h index dcf873c4a7f..758a8017bbf 100644 --- a/sched/plan_class_spec.h +++ b/sched/plan_class_spec.h @@ -1,6 +1,6 @@ // This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2023 University of California +// https://boinc.berkeley.edu +// Copyright (C) 2024 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License @@ -32,6 +32,10 @@ struct PLAN_CLASS_SPEC { bool cal; bool opencl; bool virtualbox; + bool docker; + bool docker_compose; + int min_docker_version; + int min_docker_compose_version; bool is64bit; std::vector cpu_features; double min_ncpus; diff --git a/sched/plan_class_spec.xml.sample b/sched/plan_class_spec.xml.sample index bfc1ecb031c..c75cbf973ab 100644 --- a/sched/plan_class_spec.xml.sample +++ b/sched/plan_class_spec.xml.sample @@ -120,4 +120,16 @@ 2 2 + + docker + + 270102 + + + docker_compose + + + 270102 + 32901 + diff --git a/sched/sched_customize.cpp b/sched/sched_customize.cpp index 4bf3e5d9a83..5c1afa36a64 100644 --- a/sched/sched_customize.cpp +++ b/sched/sched_customize.cpp @@ -1,6 +1,6 @@ // This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2008 University of California +// https://boinc.berkeley.edu +// Copyright (C) 2024 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License @@ -869,6 +869,24 @@ static inline bool app_plan_opencl( } } +//plan class for Docker jobs +// +static inline bool app_plan_docker( + SCHEDULER_REQUEST& sreq, char* plan_class +){ + if (!(sreq.host.docker_available)) { + add_no_work_message("Docker is not installed or is not available"); + return false; + } + + if (strstr(plan_class, "compose") && !(sreq.host.docker_compose_available)) { + add_no_work_message("Docker compose is not installed or is not available"); + return false; + } + + return true; +} + // handles vbox[32|64][_[mt]|[hwaccel]] // "mt" is tailored to the needs of CERN: // use 1 or 2 CPUs @@ -1019,6 +1037,8 @@ bool app_plan(SCHEDULER_REQUEST& sreq, char* plan_class, HOST_USAGE& hu, const W return app_plan_sse3(sreq, hu); } else if (strstr(plan_class, "vbox")) { return app_plan_vbox(sreq, plan_class, hu); + } else if (strstr(plan_class, "docker")){ + return app_plan_docker(sreq, plan_class); } log_messages.printf(MSG_CRITICAL, "Unknown plan class: %s\n", plan_class From 8c11a98bd892b7a9aedecf8dfd96c60a4ba008fe Mon Sep 17 00:00:00 2001 From: Vitalii Koshura Date: Sat, 7 Sep 2024 12:27:20 +0200 Subject: [PATCH 2/2] Fix build Signed-off-by: Vitalii Koshura --- sched/plan_class_spec.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sched/plan_class_spec.cpp b/sched/plan_class_spec.cpp index 4d3c6caf73d..99c14016dff 100644 --- a/sched/plan_class_spec.cpp +++ b/sched/plan_class_spec.cpp @@ -467,14 +467,14 @@ bool PLAN_CLASS_SPEC::check( add_no_work_message("Docker compose is not installed or is not available"); return false; } - if (sreq.host.wsl_available) { + if (!sreq.host.wsl_distros.distros.empty()) { bool docker_found = false; bool docker_compose_found = false; - for (int i = 0; i < sreq.host.wsls.wsls.size(); i++) { - if (sreq.host.wsls.wsls[i].is_docker_available) { - if (docker_compose && sreq.host.wsls.wsls[i].is_docker_compose_available) { + for (int i = 0; i < sreq.host.wsl_distros.distros.size(); i++) { + if (sreq.host.wsl_distros.distros[i].is_docker_available) { + if (docker_compose && sreq.host.wsl_distros.distros[i].is_docker_compose_available) { int maj, min, rel; - int n = sscanf(sreq.host.wsls.wsls[i].docker_version.c_str(), "%d.%d.%d", &maj, &min, &rel); + int n = sscanf(sreq.host.wsl_distros.distros[i].docker_version.c_str(), "%d.%d.%d", &maj, &min, &rel); if (n != 3) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL, @@ -499,9 +499,9 @@ bool PLAN_CLASS_SPEC::check( break; } } - if (docker_compose && sreq.host.wsls.wsls[i].is_docker_compose_available) { + if (docker_compose && sreq.host.wsl_distros.distros[i].is_docker_compose_available) { int maj, min, rel; - int n = sscanf(sreq.host.wsls.wsls[i].docker_compose_version.c_str(), "%d.%d.%d", &maj, &min, &rel); + int n = sscanf(sreq.host.wsl_distros.distros[i].docker_compose_version.c_str(), "%d.%d.%d", &maj, &min, &rel); if (n != 3) { if (config.debug_version_select) { log_messages.printf(MSG_NORMAL,