ATLAS Offline Software
Loading...
Searching...
No Matches
KubernetesDriver.cxx File Reference
#include <EventLoop/KubernetesDriver.h>
#include <fstream>
#include <sstream>
#include <TSystem.h>
#include <AsgMessaging/StatusCode.h>
#include <EventLoop/Job.h>
#include <EventLoop/ManagerData.h>
#include <EventLoop/MessageCheck.h>
#include <PathResolver/PathResolver.h>
#include <RootCoreUtils/Assert.h>
#include <RootCoreUtils/ShellExec.h>
#include <RootCoreUtils/StringUtil.h>

Go to the source code of this file.

Functions

 ClassImp (EL::KubernetesDriver) namespace EL

Function Documentation

◆ ClassImp()

ClassImp ( EL::KubernetesDriver )
Author
Nils Krumnack

the setup file we use as a template

the config file we use as a template

Definition at line 30 of file KubernetesDriver.cxx.

33{
34 void KubernetesDriver ::
35 testInvariant () const
36 {}
37
38
39
40 KubernetesDriver ::
41 KubernetesDriver ()
42 {
43 RCU_NEW_INVARIANT (this);
44 }
45
46
47
48 ::StatusCode KubernetesDriver ::
49 doManagerStep (Detail::ManagerData& data) const
50 {
51 RCU_READ_INVARIANT (this);
52 using namespace msgEventLoop;
53 ANA_CHECK (BatchDriver::doManagerStep (data));
54 switch (data.step)
55 {
56 case Detail::ManagerStep::batchScriptVar:
57 {
58 data.batchSkipReleaseSetup = true;
59 }
60 break;
61
62 case Detail::ManagerStep::submitJob:
63 case Detail::ManagerStep::doResubmit:
64 {
65 const std::string dockerImage {
66 data.options.castString(Job::optDockerImage)};
67
68 const std::string dockerOptions {
69 data.options.castString(Job::optDockerOptions)};
70 if (!dockerOptions.empty())
71 {
72 ANA_MSG_WARNING ("you specified docker options for kubernetes driver");
73 ANA_MSG_WARNING ("this is not supported in this way");
74 ANA_MSG_WARNING ("instead you need to provide your own kubernetes config file");
75 }
76
78 const std::string batchSetupFile {
79 data.options.castString(Job::optBatchSetupFile, "EventLoop/kubernetes_setup.yml")};
80
81
83 const std::string batchConfigFile {
84 data.options.castString(Job::optBatchConfigFile, "EventLoop/kubernetes_job.yml")};
85 std::string baseConfig;
86 {
87 const std::string resolved {PathResolverFindDataFile (batchConfigFile)};
88 if (resolved.empty())
89 {
90 ANA_MSG_ERROR ("failed to find batch config file " << batchConfigFile);
91 return StatusCode::FAILURE;
92 }
93 std::ifstream file (resolved.c_str());
94 if (!file)
95 {
96 ANA_MSG_ERROR ("failed to open batch config file " << resolved);
97 return StatusCode::FAILURE;
98 }
99 baseConfig = std::string (std::istreambuf_iterator<char>(file),
100 std::istreambuf_iterator<char>() );
101 }
102 baseConfig = RCU::substitute (baseConfig, "%%DOCKERIMAGE%%", dockerImage);
103 baseConfig = RCU::substitute (baseConfig, "%%SUBMITDIR%%", data.submitDir);
104
105 std::ostringstream basedirName;
106 basedirName << data.submitDir << "/tmp";
107 if (!data.resubmit)
108 {
109 if (gSystem->MakeDirectory (basedirName.str().c_str()) != 0)
110 {
111 ANA_MSG_ERROR ("failed to create directory " << basedirName.str());
112 return StatusCode::FAILURE;
113 }
114 }
115
116 const std::string jobFilePath {data.submitDir + "/job.yml"};
117 {
118 bool first {true};
119 std::ofstream jobFile (jobFilePath.c_str());
120 if (!batchSetupFile.empty())
121 {
122 const std::string resolved {PathResolverFindDataFile (batchSetupFile)};
123 if (resolved.empty())
124 {
125 ANA_MSG_ERROR ("failed to find batch setup file " << batchSetupFile);
126 return StatusCode::FAILURE;
127 }
128 std::ifstream file (resolved.c_str());
129 if (!file)
130 {
131 ANA_MSG_ERROR ("failed to open batch setup file " << resolved);
132 return StatusCode::FAILURE;
133 }
134 std::string setupConfig {std::istreambuf_iterator<char>(file),
135 std::istreambuf_iterator<char>()};
136 setupConfig = RCU::substitute (setupConfig, "%%DOCKERIMAGE%%", dockerImage);
137 setupConfig = RCU::substitute (setupConfig, "%%SUBMITDIR%%", data.submitDir);
138 jobFile << setupConfig;
139 first = false;
140 }
141
142 for (std::size_t jobIndex : data.batchJobIndices)
143 {
144 std::ostringstream dirName;
145 dirName << basedirName.str() << "/" << jobIndex;
146 // on resubmit the per-index directory already exists from the
147 // first submission, so tolerate that
148 if (gSystem->MakeDirectory (dirName.str().c_str()) != 0 && !data.resubmit)
149 {
150 ANA_MSG_ERROR ("failed to create directory " << dirName.str());
151 return StatusCode::FAILURE;
152 }
153
154 if (first)
155 first = false;
156 else
157 jobFile << "---\n";
158
159 std::string myConfig = baseConfig;
160 myConfig = RCU::substitute (myConfig, "%%JOBINDEX%%", std::to_string (jobIndex));
161 std::ostringstream command;
162 command << RCU::Shell::quote (data.submitDir) << "/submit/run " << jobIndex;
163 myConfig = RCU::substitute (myConfig, "%%COMMAND%%", command.str());
164
165 jobFile << myConfig << "\n";
166 }
167 }
168
169 std::ostringstream cmd;
170 cmd << "kubectl create -f " << jobFilePath;
171 RCU::Shell::exec (cmd.str());
172 data.submitted = true;
173 }
174 break;
175
176 default:
177 break;
178 }
179 return ::StatusCode::SUCCESS;
180 }
181}
#define RCU_NEW_INVARIANT(x)
Definition Assert.h:221
#define RCU_READ_INVARIANT(x)
Definition Assert.h:217
#define ANA_MSG_ERROR(xmsg,...)
Macro printing error messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
#define ANA_MSG_WARNING(xmsg,...)
Macro printing warning messages.
std::string PathResolverFindDataFile(const std::string &logical_file_name)
bool first
Definition DeMoScan.py:534
void exec(const std::string &cmd)
effects: execute the given command guarantee: strong failures: out of memory II failures: system fail...
Definition ShellExec.cxx:27
std::string quote(const std::string &name)
effects: quote the given name to protect it from the shell returns: the quoted name guarantee: strong...
Definition ShellExec.cxx:65
std::string substitute(std::string_view str, std::string_view pattern, std::string_view with)
effects: substitute all occurences of "pattern" with "with" in the string "str" returns: the substitu...
TFile * file