Skip to content

Commit bfe56f3

Browse files
authored
Measure Docker container memory usage (#947)
* Deprecated use of --record-container-id, container-ids are now saved by default (temporarily) or in dir specified by --cidfile-dir
1 parent e414985 commit bfe56f3

File tree

13 files changed

+381
-195
lines changed

13 files changed

+381
-195
lines changed

cwltool/argparser.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,23 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
4848
dest="rm_container")
4949

5050
cidgroup = parser.add_argument_group(
51-
"Options for recording the Docker container identifier into a file")
51+
"Options for recording the Docker container identifier into a file.")
52+
# Disabled as containerid is now saved by default
5253
cidgroup.add_argument("--record-container-id", action="store_true",
5354
default=False,
54-
help="If enabled, store the Docker container ID into a file. "
55-
"See --cidfile-dir to specify the directory.",
55+
help = argparse.SUPPRESS,
5656
dest="record_container_id")
5757

5858
cidgroup.add_argument(
59-
"--cidfile-dir", type=Text, help="Directory for storing the Docker "
60-
"container ID file. The default is the current directory",
59+
"--cidfile-dir", type=Text, help="Store the Docker "
60+
"container ID into a file in the specifed directory.",
6161
default=None, dest="cidfile_dir")
6262

6363
cidgroup.add_argument(
6464
"--cidfile-prefix", type=Text,
6565
help="Specify a prefix to the container ID filename. "
66-
"Final file name will be followed by a timestamp. The default is no prefix.",
66+
"Final file name will be followed by a timestamp. "
67+
"The default is no prefix.",
6768
default=None, dest="cidfile_prefix")
6869

6970
parser.add_argument("--tmpdir-prefix", type=Text,

cwltool/context.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ def __init__(self, kwargs=None):
122122
self.on_error = "stop" # type: Text
123123
self.strict_memory_limit = False # type: bool
124124

125-
self.record_container_id = False
126125
self.cidfile_dir = None
127126
self.cidfile_prefix = None
128127

cwltool/docker.py

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import tempfile
1111
import threading
1212
from io import open # pylint: disable=redefined-builtin
13-
from typing import Dict, List, MutableMapping, Optional, Set
13+
from typing import Dict, List, MutableMapping, Optional, Set, Tuple
1414

1515
import requests
1616
from typing_extensions import Text # pylint: disable=unused-import
@@ -200,8 +200,8 @@ def append_volume(runtime, source, target, writable=False):
200200
# type: (List[Text], Text, Text, bool) -> None
201201
"""Add binding arguments to the runtime list."""
202202
runtime.append(u"--volume={}:{}:{}".format(
203-
docker_windows_path_adjust(source),
204-
docker_windows_path_adjust(target), "rw" if writable else "ro"))
203+
docker_windows_path_adjust(source), target,
204+
"rw" if writable else "ro"))
205205

206206
def add_file_or_directory_volume(self,
207207
runtime, # type: List[Text]
@@ -215,9 +215,10 @@ def add_file_or_directory_volume(self,
215215
self.append_volume(runtime, volume.resolved, volume.target)
216216

217217
def add_writable_file_volume(self,
218-
runtime, # type: List[Text]
219-
volume, # type: MapperEnt
220-
host_outdir_tgt # type: Optional[Text]
218+
runtime, # type: List[Text]
219+
volume, # type: MapperEnt
220+
host_outdir_tgt, # type: Optional[Text]
221+
tmpdir_prefix # type: Text
221222
): # type: (...) -> None
222223
"""Append a writable file mapping to the runtime option list."""
223224
if self.inplace_update:
@@ -229,7 +230,7 @@ def add_writable_file_volume(self,
229230
# which is already going to be mounted
230231
shutil.copy(volume.resolved, host_outdir_tgt)
231232
else:
232-
tmpdir = tempfile.mkdtemp(dir=self.tmpdir)
233+
tmpdir = tempfile.mkdtemp(dir=tmpdir_prefix)
233234
file_copy = os.path.join(
234235
tmpdir, os.path.basename(volume.resolved))
235236
shutil.copy(volume.resolved, file_copy)
@@ -238,16 +239,17 @@ def add_writable_file_volume(self,
238239
ensure_writable(host_outdir_tgt or file_copy)
239240

240241
def add_writable_directory_volume(self,
241-
runtime, # type: List[Text]
242-
volume, # type: MapperEnt
243-
host_outdir_tgt # type: Optional[Text]
242+
runtime, # type: List[Text]
243+
volume, # type: MapperEnt
244+
host_outdir_tgt, # type: Optional[Text]
245+
tmpdir_prefix # type: Text
244246
): # type: (...) -> None
245247
"""Append a writable directory mapping to the runtime option list."""
246248
if volume.resolved.startswith("_:"):
247249
# Synthetic directory that needs creating first
248250
if not host_outdir_tgt:
249251
new_dir = os.path.join(
250-
tempfile.mkdtemp(dir=self.tmpdir),
252+
tempfile.mkdtemp(dir=tmpdir_prefix),
251253
os.path.basename(volume.target))
252254
self.append_volume(runtime, new_dir, volume.target,
253255
writable=True)
@@ -259,7 +261,7 @@ def add_writable_directory_volume(self,
259261
writable=True)
260262
else:
261263
if not host_outdir_tgt:
262-
tmpdir = tempfile.mkdtemp(dir=self.tmpdir)
264+
tmpdir = tempfile.mkdtemp(dir=tmpdir_prefix)
263265
new_dir = os.path.join(
264266
tmpdir, os.path.basename(volume.resolved))
265267
shutil.copytree(volume.resolved, new_dir)
@@ -270,8 +272,10 @@ def add_writable_directory_volume(self,
270272
shutil.copytree(volume.resolved, host_outdir_tgt)
271273
ensure_writable(host_outdir_tgt or new_dir)
272274

273-
def create_runtime(self, env, runtimeContext):
274-
# type: (MutableMapping[Text, Text], RuntimeContext) -> List
275+
def create_runtime(self,
276+
env, # type: MutableMapping[Text, Text]
277+
runtimeContext # type: RuntimeContext
278+
): # type: (...) -> Tuple[List[Text], Optional[Text]]
275279
any_path_okay = self.builder.get_requirement("DockerRequirement")[1] \
276280
or False
277281
user_space_docker_cmd = runtimeContext.user_space_docker_cmd
@@ -284,19 +288,18 @@ def create_runtime(self, env, runtimeContext):
284288
runtime = [user_space_docker_cmd, u"run"]
285289
else:
286290
runtime = [u"docker", u"run", u"-i"]
287-
288-
runtime.append(u"--volume=%s:%s:rw" % (
289-
docker_windows_path_adjust(os.path.realpath(self.outdir)),
290-
self.builder.outdir))
291-
runtime.append(u"--volume=%s:%s:rw" % (
292-
docker_windows_path_adjust(os.path.realpath(self.tmpdir)), "/tmp"))
293-
291+
self.append_volume(runtime, os.path.realpath(self.outdir),
292+
self.builder.outdir, writable=True)
293+
self.append_volume(runtime, os.path.realpath(self.tmpdir), "/tmp",
294+
writable=True)
294295
self.add_volumes(self.pathmapper, runtime, any_path_okay=True,
295-
secret_store=runtimeContext.secret_store)
296+
secret_store=runtimeContext.secret_store,
297+
tmpdir_prefix=runtimeContext.tmpdir_prefix)
296298
if self.generatemapper is not None:
297299
self.add_volumes(
298300
self.generatemapper, runtime, any_path_okay=any_path_okay,
299-
secret_store=runtimeContext.secret_store)
301+
secret_store=runtimeContext.secret_store,
302+
tmpdir_prefix=runtimeContext.tmpdir_prefix)
300303

301304
if user_space_docker_cmd:
302305
runtime = [x.replace(":ro", "") for x in runtime]
@@ -338,25 +341,26 @@ def create_runtime(self, env, runtimeContext):
338341
runtime.append(u"--env=HOME=%s" % self.builder.outdir)
339342

340343
# add parameters to docker to write a container ID file
341-
if runtimeContext.record_container_id is True:
344+
345+
if runtimeContext.cidfile_dir:
342346
cidfile_dir = runtimeContext.cidfile_dir
343-
if cidfile_dir is not None:
344-
if not os.path.isdir(cidfile_dir):
345-
_logger.error("--cidfile-dir %s error:\n%s", cidfile_dir,
346-
cidfile_dir + " is not a directory or "
347-
"directory doesn't exist, please check it first")
348-
exit(2)
349-
if not os.path.exists(cidfile_dir):
350-
_logger.error("--cidfile-dir %s error:\n%s", cidfile_dir,
351-
"directory doesn't exist, please create it first")
352-
exit(2)
353-
else:
354-
cidfile_dir = os.getcwd()
355-
cidfile_name = datetime.datetime.now().strftime("%Y%m%d%H%M%S-%f") + ".cid"
356-
if runtimeContext.cidfile_prefix is not None:
357-
cidfile_name = str(runtimeContext.cidfile_prefix + "-" + cidfile_name)
358-
cidfile_path = os.path.join(cidfile_dir, cidfile_name)
359-
runtime.append(u"--cidfile=%s" % cidfile_path)
347+
if not os.path.exists(str(cidfile_dir)):
348+
_logger.error("--cidfile-dir %s error:\n%s", cidfile_dir,
349+
"directory doesn't exist, please create it first")
350+
exit(2)
351+
if not os.path.isdir(cidfile_dir):
352+
_logger.error("--cidfile-dir %s error:\n%s", cidfile_dir,
353+
cidfile_dir + " is not a directory, "
354+
"please check it first")
355+
exit(2)
356+
else:
357+
cidfile_dir = os.getcwd()
358+
359+
cidfile_name = datetime.datetime.now().strftime("%Y%m%d%H%M%S-%f") + ".cid"
360+
if runtimeContext.cidfile_prefix is not None:
361+
cidfile_name = str(runtimeContext.cidfile_prefix + "-" + cidfile_name)
362+
cidfile_path = os.path.join(cidfile_dir, cidfile_name)
363+
runtime.append(u"--cidfile=%s" % cidfile_path)
360364

361365
for key, value in self.environment.items():
362366
runtime.append(u"--env=%s=%s" % (key, value))
@@ -373,4 +377,4 @@ def create_runtime(self, env, runtimeContext):
373377
"--strict-memory-limit for increased portability "
374378
"assurance.", self.name)
375379

376-
return runtime
380+
return runtime, cidfile_path

0 commit comments

Comments
 (0)