Source code for flash.flmake.run
# Python imports
import os
import shutil
import subprocess
import json
import uuid
import collections
import hashlib
# local imports
# relative imports needed
from .. import FLASH_SRC_DIR, MPIRUN_CMD
from ..utils import warning
from . import logger
from . import setup_parse
from . import setup_globals
from .setup_globals import gvars
from .utils import desc_cmd_metadata
from ..dsl import runtime_parameters
CP_OBJ_FILES = ['flash4']
[docs]def init_rundir():
"""Initializes run_dir and run_id in gvars."""
gvars.init(FLASH_SRC_DIR)
#setup_parse.parse() # FIXME Eats mpirun opts
# use default run id
if not gvars.run_id:
gvars.run_id = uuid.uuid4().hex[:8]
# use default rundir
if not gvars.run_dir:
gvars.run_dir = gvars.run_dir_prefix + gvars.run_id
[docs]def main(opts, rc, msg):
"""Executes flash in run directory."""
# init directory
init_rundir()
if not os.path.isdir(gvars.run_dir):
os.mkdir(gvars.run_dir)
# init runtime files with build files.
cp_run_files = {f: os.path.join(gvars.project_build_dir, f) for f in CP_OBJ_FILES}
# add datafiles (from setup) to runtime files needed
with open(gvars.desc_filename) as desc_file:
desc = json.load(desc_file)
from_setup = {f: os.path.join(gvars.project_setup_dir, f) for f in desc['setup']['datafiles']}
cp_run_files.update(from_setup)
# copy over runtime files
for f in cp_run_files:
if os.path.isfile(cp_run_files[f]):
shutil.copy2(cp_run_files[f], os.path.join(gvars.run_dir, f))
# apply run control
rcparams = {}
if 'parameters' in rc:
# ensure parameters is dict-like.
rcparams = rc['parameters']
if callable(rcparams):
rcparams = rcparams()
assert isinstance(rcparams, collections.Mapping)
# update the parfile if params non-empty
if 0 < len(rcparams):
parfile = os.path.join(gvars.run_dir, 'flash.par')
params = runtime_parameters.load(parfile)
params.update(rcparams)
runtime_parameters.dump(params, parfile)
# Writes the flash description file for running.
desc['run'] = desc_cmd_metadata()
desc_run = desc['run']
desc_run['id'] = gvars.run_id
desc_run['history'] = []
flash_executable = os.path.join(gvars.run_dir, "flash4")
with open(flash_executable, 'rb') as f:
desc_run['flash_executable_hash'] = hashlib.sha1(f.read()).hexdigest()
desc_run['flash_executable_mtime'] = os.path.getmtime(flash_executable)
desc_run['reproducible'] = desc['build'] and \
desc_run['flash_executable_hash'] == desc['build']['flash_executable_hash']
if not desc_run['reproducible']:
print message("Irreproducible: flash executable modifided between build and run!")
with open(os.path.join(gvars.run_dir, gvars.desc_filename), 'w') as f:
json.dump(desc, f, indent=2)
# quit sanely, if desired
if '--dry-run' in opts:
return 0
# log this attempted run
if msg is None:
msg = "running flash"
msg += " with: " + str(rcparams) if 0 < len(rcparams) else ""
logger.info(msg, "run", desc_run['id'], gvars.run_dir)
# run flash
cmd = [MPIRUN_CMD] + opts + ["./flash4"]
try:
rtn = subprocess.check_call(cmd, cwd=gvars.run_dir)
finally:
map(os.remove, [f for f in os.listdir('.') if 0 == os.path.getsize(f)])
return rtn
[docs]def usage():
"""Print usage info and exits."""
msg = ("usage: flmake run [--dry-run] [options]\n\n"
"Runs the flash executable by calling out to\n"
"the '{0}' utility. All options given to this\n"
"command are transparently passed down.\n"
"FLASH is executed in a new run directory which\n"
"is given a unique id number upon each call.\n"
"If '--dry-run' is present, no execution is done.\n\n").format(MPIRUN_CMD)
run_header = "{0} HELP:\n".format(MPIRUN_CMD.upper())
run_header += "-" * (len(run_header) - 1)
msg += run_header + "\n"
msg += subprocess.check_output([MPIRUN_CMD, '--help'], stderr=subprocess.STDOUT)[:-1]
return msg