def run_program(cmd, output='mpi_run.out', env=None): """Execute python script with mpi. Args: cmd (list): cmd to run output (str): where to write stdout and stderr env (dict): what to pass as env """ from sirepo import simulation_db try: cmd = [ 'mpiexec', '--bind-to', 'none', '-n', str(cfg.cores), ] + cmd pksubprocess.check_call_with_signals( cmd, msg=pkdp, output=str(output), env=env, ) except Exception as e: simulation_db.write_result({'state': 'error', 'error': str(e)}) raise
def twiss_to_madx(elegant_twiss_file, madx_twiss_file): outfile = 'sdds_output.txt' twiss_file = 'twiss-with-mu.sdds' # convert elegant psix to mad-x MU, rad --> rad / 2pi pksubprocess.check_call_with_signals([ 'sddsprocess', elegant_twiss_file, '-define=column,mux,psix 2 pi * /', '-define=column,muy,psiy 2 pi * /', twiss_file, ], output=outfile, env=elegant_common.subprocess_env()) pksubprocess.check_call_with_signals([ 'sdds2stream', twiss_file, '-columns={}'.format(','.join( map(lambda x: x[0], _ELEGANT_TO_MADX_COLUMNS))), ], output=outfile, env=elegant_common.subprocess_env()) lines = pkio.read_text(outfile).split('\n') header = '* {}\n$ \n'.format(' '.join( map(lambda x: x[1], _ELEGANT_TO_MADX_COLUMNS))) pkio.write_text(madx_twiss_file, header + '\n'.join(lines) + '\n')
def nginx_proxy(): """Starts nginx in container. Used for development only. """ import sirepo.feature_config assert pkconfig.channel_in('dev') run_dir = _run_dir().join('nginx_proxy').ensure(dir=True) with pkio.save_chdir(run_dir) as d: f = run_dir.join('default.conf') c = PKDict(_cfg()).pkupdate(run_dir=str(d)) if 'jupyterhublogin' in sirepo.feature_config.cfg().sim_types: import sirepo.sim_api.jupyterhublogin import sirepo.server sirepo.server.init() c.pkupdate( jupyterhub_root=sirepo.sim_api.jupyterhublogin.cfg.uri_root, ) pkjinja.render_resource('nginx_proxy.conf', c, output=f) cmd = [ 'nginx', '-c', str(f), ] pksubprocess.check_call_with_signals(cmd)
def _run_jspec(data): _elegant_to_madx(data['models']['ring']) exec(pkio.read_text(template_common.PARAMETERS_PYTHON_FILE), locals(), locals()) jspec_filename = template.JSPEC_INPUT_FILENAME pkio.write_text(jspec_filename, jspec_file) pksubprocess.check_call_with_signals(['jspec', jspec_filename], msg=pkdlog, output=template.JSPEC_LOG_FILE) return pkio.read_text(template.JSPEC_LOG_FILE)
def _run_jspec(data): _elegant_to_madx(data['models']['ring']) r = template_common.exec_parameters() f = template.JSPEC_INPUT_FILENAME pkio.write_text(f, r.jspec_file) pksubprocess.check_call_with_signals(['jspec', f], msg=pkdlog, output=template.JSPEC_LOG_FILE)
def _run_jspec(run_dir): with pkio.save_chdir(run_dir): data = simulation_db.read_json(template_common.INPUT_BASE_NAME) _elegant_to_madx(data['models']['ring']) exec(pkio.read_text(template_common.PARAMETERS_PYTHON_FILE), locals(), locals()) jspec_filename = template.JSPEC_INPUT_FILENAME pkio.write_text(jspec_filename, jspec_file) pksubprocess.check_call_with_signals(['jspec', jspec_filename], msg=pkdp, output=template.JSPEC_LOG_FILE) return pkio.read_text(template.JSPEC_LOG_FILE)
def _run_madx(filename=template.MADX_INPUT_FILE): pksubprocess.check_call_with_signals( ['madx', filename], msg=pkdlog, output=template.MADX_LOG_FILE, ) # fixup madx munged file names for f in glob.glob('*.tfsone'): n = re.sub(r'tfsone$', 'tfs', f) os.rename(f, n)
def _run_dose_calculation(data, cfg_dir): if not feature_config.cfg().rs4pi_dose_calc: dicom_dose = _run_dose_calculation_fake(data, cfg_dir) else: pksubprocess.check_call_with_signals( ['bash', str(cfg_dir.join(template.DOSE_CALC_SH))]) dicom_dose = template.generate_rtdose_file(data, cfg_dir) data['models']['dicomDose'] = dicom_dose # save results into simulation input data file, this is needed for further calls to get_simulation_frame() simulation_db.write_json(template_common.INPUT_BASE_NAME, data) template_common.write_sequential_result(PKDict(dicomDose=dicom_dose))
def _run_dose_calculation(data, cfg_dir): if not feature_config.cfg.rs4pi_dose_calc: dicom_dose = _run_dose_calculation_fake(data, cfg_dir) else: with pkio.save_chdir(cfg_dir): pksubprocess.check_call_with_signals(['bash', str(cfg_dir.join(template.DOSE_CALC_SH))]) dicom_dose = template.generate_rtdose_file(data, cfg_dir) data['models']['dicomDose'] = dicom_dose # save results into simulation input data file, this is needed for further calls to get_simulation_frame() simulation_db.write_json(template_common.INPUT_BASE_NAME, data) simulation_db.write_result({ 'dicomDose': dicom_dose, })
def uwsgi(): """Starts UWSGI server""" run_dir = _run_dir() with pkio.save_chdir(run_dir): values = dict(pkcollections.map_items(cfg)) values['logto'] = None if pkconfig.channel_in('dev') else str(run_dir.join('uwsgi.log')) # uwsgi.py must be first, because values['uwsgi_py'] referenced by uwsgi.yml for f in ('uwsgi.py', 'uwsgi.yml'): output = run_dir.join(f) values[f.replace('.', '_')] = str(output) pkjinja.render_resource(f, values, output=output) cmd = ['uwsgi', '--yaml=' + values['uwsgi_yml']] pksubprocess.check_call_with_signals(cmd)
def run(cfg_dir): pksubprocess.check_call_with_signals( [sys.executable, template_common.PARAMETERS_PYTHON_FILE], ) data = simulation_db.read_json(template_common.INPUT_BASE_NAME) if data.report == 'heightWeightReport': res = _report( 'Dog Height and Weight Over Time', ('height', 'weight'), data, ) else: raise AssertionError('unknown report: {}'.format(data.report)) template_common.write_sequential_result(res)
def rabbitmq(): assert pkconfig.channel_in('dev') run_dir = _run_dir().join('rabbitmq').ensure(dir=True) with pkio.save_chdir(run_dir): cmd = [ 'docker', 'run', '--env=RABBITMQ_NODE_IP_ADDRESS=' + cfg.ip, '--net=host', '--rm', '--volume={}:/var/lib/rabbitmq'.format(run_dir), 'rabbitmq:management', ] pksubprocess.check_call_with_signals(cmd)
def _run_opal(with_mpi=False): if with_mpi and mpi.cfg.cores < 2: with_mpi = False if with_mpi: mpi.run_program( ['opal', template.OPAL_INPUT_FILE], output=template.OPAL_OUTPUT_FILE, ) else: pksubprocess.check_call_with_signals( ['opal', template.OPAL_INPUT_FILE], output=template.OPAL_OUTPUT_FILE, msg=pkdlog, )
def _run_opal(with_mpi=False, compute_positions=False): if with_mpi and mpi.cfg.cores < 2: with_mpi = False if with_mpi: mpi.run_program( ['opal', template.OPAL_INPUT_FILE], output=template.OPAL_OUTPUT_FILE, ) else: pksubprocess.check_call_with_signals( ['opal', template.OPAL_INPUT_FILE], output=template.OPAL_OUTPUT_FILE, msg=pkdlog, ) if compute_positions: template_common.exec_parameters(template.OPAL_POSITION_FILE)
def _run_elegant(bunch_report=False, with_mpi=False): exec(pkio.read_text(template_common.PARAMETERS_PYTHON_FILE), locals(), locals()) if bunch_report and re.search('\&sdds_beam\s', elegant_file): return pkio.write_text('elegant.lte', lattice_file) ele = 'elegant.ele' pkio.write_text(ele, elegant_file) kwargs = { 'output': ELEGANT_LOG_FILE, 'env': elegant_common.subprocess_env(), } #TODO(robnagler) Need to handle this specially, b/c different binary if execution_mode == 'parallel' and with_mpi and mpi.cfg.cores > 1: return mpi.run_program(['Pelegant', ele], **kwargs) pksubprocess.check_call_with_signals(['elegant', ele], msg=pkdp, **kwargs)
def run_elegant(with_mpi=False): # also used by pkcli.rcscon r = template_common.exec_parameters() pkio.write_text('elegant.lte', r.lattice_file) ele = 'elegant.ele' pkio.write_text(ele, r.elegant_file) kwargs = { 'output': ELEGANT_LOG_FILE, 'env': elegant_common.subprocess_env(), } #TODO(robnagler) Need to handle this specially, b/c different binary if r.execution_mode == 'parallel' and with_mpi and mpi.cfg.cores > 1: mpi.run_program(['Pelegant', ele], **kwargs) else: pksubprocess.check_call_with_signals(['elegant', ele], msg=pkdlog, **kwargs)
def start_simulation(cmd, run_dir): """Call simulation's in run_background with run_dir Args: cmd (list): simulation command line run_dir (str): directory """ # Avoid circular import from sirepo import simulation_db run_dir = py.path.local(run_dir) simulation_db.hack_nfs_write_status('running', run_dir) with pkio.save_chdir(run_dir): pksubprocess.check_call_with_signals( cmd, msg=pkdlog, output=str(run_dir.join(template_common.RUN_LOG)), )
def _run_elegant(bunch_report=False, with_mpi=False): exec(pkio.read_text(template_common.PARAMETERS_PYTHON_FILE), locals(), locals()) if bunch_report and re.search('\&sdds_beam\s', elegant_file): return pkio.write_text('elegant.lte', lattice_file) ele = 'elegant.ele' pkio.write_text(ele, elegant_file) # TODO(robnagler) Need to handle this specially, b/c different binary env = copy.deepcopy(os.environ) env['RPN_DEFNS'] = pkresource.filename('defns.rpn') if with_mpi and mpi.cfg.cores > 1: return mpi.run_program(['Pelegant', ele], output=ELEGANT_LOG_FILE, env=env) pksubprocess.check_call_with_signals( ['elegant', ele], output=ELEGANT_LOG_FILE, env=env, msg=pkdp, )
def rabbitmq(): assert pkconfig.channel_in('dev') run_dir = _run_dir().join('rabbitmq').ensure(dir=True) with pkio.save_chdir(run_dir): cmd = [ 'docker', 'run', '--env=RABBITMQ_NODE_IP_ADDRESS=' + cfg.ip, '--net=host', '--rm', '--volume={}:/var/lib/rabbitmq'.format(run_dir), 'rabbitmq:management', ] try: pksubprocess.check_call_with_signals(cmd) except OSError as e: if e.errno == errno.ENOENT: pkcli.command_error('docker is not installed')
def _run_elegant(bunch_report=False, with_mpi=False): exec(pkio.read_text(template_common.PARAMETERS_PYTHON_FILE), locals(), locals()) pkio.write_text('elegant.lte', lattice_file) ele = 'elegant.ele' pkio.write_text(ele, elegant_file) kwargs = { 'output': ELEGANT_LOG_FILE, 'env': elegant_common.subprocess_env(), } try: #TODO(robnagler) Need to handle this specially, b/c different binary if execution_mode == 'parallel' and with_mpi and mpi.cfg.cores > 1: mpi.run_program(['Pelegant', ele], **kwargs) else: pksubprocess.check_call_with_signals(['elegant', ele], msg=pkdlog, **kwargs) except Exception as e: # ignore elegant failures - errors will be parsed from the log pass
def nginx_proxy(): """Starts nginx in container. Used for development only. """ assert pkconfig.channel_in('dev') run_dir = _run_dir().join('nginx_proxy').ensure(dir=True) with pkio.save_chdir(run_dir): f = run_dir.join('default.conf') pkjinja.render_resource('nginx_proxy.conf', cfg(), output=f) cmd = [ 'docker', 'run', '--net=host', '--rm', '--volume={}:/etc/nginx/conf.d/default.conf'.format(f), 'nginx', ] pksubprocess.check_call_with_signals(cmd)
def twiss_to_madx(elegant_twiss_file, madx_twiss_file): outfile = 'sdds_output.txt' twiss_file = 'twiss-with-mu.sdds' # convert elegant psix to mad-x MU, rad --> rad / 2pi pksubprocess.check_call_with_signals([ 'sddsprocess', elegant_twiss_file, '-define=column,mux,psix 2 pi * /', '-define=column,muy,psiy 2 pi * /', twiss_file, ], output=outfile, env=elegant_common.subprocess_env()) pksubprocess.check_call_with_signals([ 'sdds2stream', twiss_file, '-columns={}'.format(','.join(map(lambda x: x[0], _ELEGANT_TO_MADX_COLUMNS))), ], output=outfile, env=elegant_common.subprocess_env()) lines = pkio.read_text(outfile).split('\n') header = '* {}\n$ \n'.format(' '.join(map(lambda x: x[1], _ELEGANT_TO_MADX_COLUMNS))) pkio.write_text(madx_twiss_file, header + '\n'.join(lines) + '\n')
def nginx_proxy(): """Starts nginx in container. Used for development only. """ assert pkconfig.channel_in('dev') run_dir = _run_dir().join('nginx_proxy').ensure(dir=True) with pkio.save_chdir(run_dir): f = run_dir.join('default.conf') values = dict(pkcollections.map_items(cfg)) pkjinja.render_resource('nginx_proxy.conf', values, output=f) cmd = [ 'docker', 'run', '--net=host', '--rm', '--volume={}:/etc/nginx/conf.d/default.conf'.format(f), 'nginx', ] pksubprocess.check_call_with_signals(cmd)
def nginx_proxy(): """Starts nginx in container. Used for development only. """ assert pkconfig.channel_in('dev') run_dir = _run_dir().join('nginx_proxy').ensure(dir=True) with pkio.save_chdir(run_dir) as d: f = run_dir.join('default.conf') pkjinja.render_resource( 'nginx_proxy.conf', PKDict(cfg()).pkupdate(run_dir=str(d)), output=f, ) cmd = [ 'nginx', '-c', str(f), ] pksubprocess.check_call_with_signals(cmd)
def uwsgi(): """Starts UWSGI server""" in_dev = pkconfig.channel_in('dev') if in_dev: from sirepo import server, runner # uwsgi doesn't pass signals right so can't use _Background if not issubclass(server.cfg.job_queue, runner.Celery): pkcli.command_error( 'uwsgi only works if sirepo.server.cfg.job_queue=_Celery') run_dir = _run_dir() with pkio.save_chdir(run_dir): values = dict(pkcollections.map_items(cfg)) values['logto'] = None if in_dev else str(run_dir.join('uwsgi.log')) # uwsgi.py must be first, because values['uwsgi_py'] referenced by uwsgi.yml for f in ('uwsgi.py', 'uwsgi.yml'): output = run_dir.join(f) values[f.replace('.', '_')] = str(output) pkjinja.render_resource(f, values, output=output) cmd = ['uwsgi', '--yaml=' + values['uwsgi_yml']] pksubprocess.check_call_with_signals(cmd)
def uwsgi(): """Starts UWSGI server""" in_dev = pkconfig.channel_in('dev') if in_dev: from sirepo import server, runner # uwsgi doesn't pass signals right so can't use _Background if not issubclass(server.cfg.job_queue, runner.Celery): pkcli.command_error('uwsgi only works if sirepo.server.cfg.job_queue=_Celery') db_dir =_db_dir() run_dir = _run_dir() with pkio.save_chdir(run_dir): values = dict(pkcollections.map_items(cfg)) values['logto'] = None if in_dev else str(run_dir.join('uwsgi.log')) # uwsgi.py must be first, because values['uwsgi_py'] referenced by uwsgi.yml for f in ('uwsgi.py', 'uwsgi.yml'): output = run_dir.join(f) values[f.replace('.', '_')] = str(output) pkjinja.render_resource(f, values, output=output) cmd = ['uwsgi', '--yaml=' + values['uwsgi_yml']] pksubprocess.check_call_with_signals(cmd)
def run(cfg_dir): with pkio.save_chdir(cfg_dir): try: pksubprocess.check_call_with_signals( [sys.executable, template_common.PARAMETERS_PYTHON_FILE], ) except Exception as e: pkdlog('script failed: dir={} err={}', cfg_dir, e) simulation_db.write_result({ 'error': 'program error occured', }) return data = simulation_db.read_json(template_common.INPUT_BASE_NAME) if data.report == 'heightWeightReport': res = _report( 'Dog Height and Weight Over Time', ('height', 'weight'), data, ) else: raise AssertionError('unknown report: {}'.format(data.report)) simulation_db.write_result(res)
def _run_elegant(bunch_report=False, with_mpi=False): exec(pkio.read_text(template_common.PARAMETERS_PYTHON_FILE), locals(), locals()) if bunch_report and re.search('\&sdds_beam\s', elegant_file): return pkio.write_text('elegant.lte', lattice_file) ele = 'elegant.ele' pkio.write_text(ele, elegant_file) # TODO(robnagler) Need to handle this specially, b/c different binary env = copy.deepcopy(os.environ) env['RPN_DEFNS'] = pkresource.filename('defns.rpn') if execution_mode == 'parallel' and with_mpi and mpi.cfg.cores > 1: return mpi.run_program(['Pelegant', ele], output=ELEGANT_LOG_FILE, env=env) pksubprocess.check_call_with_signals( ['elegant', ele], output=ELEGANT_LOG_FILE, env=env, msg=pkdp, )
def jupyterhub(): import sirepo.template assert pkconfig.channel_in('dev') sirepo.template.assert_sim_type('jupyterhublogin') try: import jupyterhub except ImportError: raise AssertionError('jupyterhub not installed. run `pip install jupyterhub`') import sirepo.sim_api.jupyterhublogin import sirepo.server sirepo.server.init() with pkio.save_chdir(_run_dir().join('jupyterhub').ensure(dir=True)) as d: f = d.join('conf.py') pkjinja.render_resource( 'jupyterhub_conf.py', PKDict(_cfg()).pkupdate(**sirepo.sim_api.jupyterhublogin.cfg), output=f, ) pksubprocess.check_call_with_signals(('jupyterhub', '-f', str(f)))
def run_program(cmd, output='mpi_run.out', env=None): """Execute python script with mpi. Args: cmd (list): cmd to run output (str): where to write stdout and stderr env (dict): what to pass as env """ cmd = [ 'mpiexec', '--bind-to', 'none', '-n', str(cfg.cores), ] + cmd pksubprocess.check_call_with_signals( cmd, msg=pkdlog, output=str(output), env=env, )
def test_check_call_with_signals(): from pykern import pksubprocess from pykern import pkunit import os import signal messages = [] def msg(*args): s = args[0] messages.append(s.format(*args[1:])) signals = [] def signal_handler(sig, frame): signals.append(sig) with pkunit.save_chdir_work(): with open('true.out', 'w+') as o: pksubprocess.check_call_with_signals(['true'], output=o) o.seek(0) actual = o.read() assert '' == actual, \ 'Expecting empty output "{}"'.format(actual) with open('echo.out', 'w+') as o: messages = [] tag = 'xyzzy' pksubprocess.check_call_with_signals(['echo', tag], output=o, msg=msg) o.seek(0) actual = o.read() assert tag in actual, \ '"{}" not in output "{}"'.format(tag, actual) assert 'started' in messages[0], \ '"started" not in messages[0] "{}"'.format(messages[0]) assert 'normal exit' in messages[1], \ '"normal exit" not in messages[1] "{}"'.format(messages[1]) with open('kill.out', 'w+') as o: messages = [] signals = [] signal.signal(signal.SIGTERM, signal_handler) with open('kill.sh', 'w') as f: f.write('kill -TERM {}\nsleep 10'.format(os.getpid())) cmd = ['sh', 'kill.sh'] with pytest.raises(RuntimeError): pksubprocess.check_call_with_signals(cmd, output=o, msg=msg) o.seek(0) actual = o.read() assert '' == actual, \ 'Expecting empty output "{}"'.format(actual) assert signal.SIGTERM in signals, \ '"SIGTERM" not in signals "{}"'.format(signals) assert 'error exit' in messages[1], \ '"error exit" not in messages[1] "{}"'.format(messages[1])
def run(cfg_dir): with pkio.save_chdir(cfg_dir): data = simulation_db.read_json(template_common.INPUT_BASE_NAME) pksubprocess.check_call_with_signals(['opal', 'opal.in'], msg=pkdlog) if data['report'] == 'twissReport': simulation_db.write_result(_extract_twiss_report(data))
def run_background(cfg_dir): data = simulation_db.read_json(template_common.INPUT_BASE_NAME) with pkio.save_chdir(cfg_dir): pksubprocess.check_call_with_signals(['opal', 'opal.in'], msg=pkdlog) simulation_db.write_result({})
def test_check_call_with_signals(): from pykern import pksubprocess from pykern import pkunit import os import signal import subprocess import time messages = [] def msg(*args): s = args[0] messages.append(s.format(*args[1:])) signals = [] def signal_handler(sig, frame): signals.append(sig) with pkunit.save_chdir_work(): with open('true.out', 'w+') as o: pksubprocess.check_call_with_signals(['true'], output=o) o.seek(0) actual = o.read() assert '' == actual, \ 'Expecting empty output "{}"'.format(actual) with open('echo.out', 'w+') as o: messages = [] tag = 'xyzzy' pksubprocess.check_call_with_signals(['echo', tag], output=o, msg=msg) o.seek(0) actual = o.read() assert tag in actual, \ '"{}" not in output "{}"'.format(tag, actual) assert 'started' in messages[0], \ '"started" not in messages[0] "{}"'.format(messages[0]) assert 'normal exit' in messages[1], \ '"normal exit" not in messages[1] "{}"'.format(messages[1]) with open('kill.out', 'w+') as o: messages = [] signals = [] signal.signal(signal.SIGTERM, signal_handler) with open('kill.sh', 'w') as f: f.write('kill -TERM {}\nsleep 10'.format(os.getpid())) cmd = ['sh', 'kill.sh'] with pytest.raises(RuntimeError): pksubprocess.check_call_with_signals(cmd, output=o, msg=msg) o.seek(0) actual = o.read() assert '' == actual, \ 'Expecting empty output "{}"'.format(actual) assert signal.SIGTERM in signals, \ '"SIGTERM" not in signals "{}"'.format(signals) assert 'error exit' in messages[1], \ '"error exit" not in messages[1] "{}"'.format(messages[1]) with open('kill.out', 'w+') as o: messages = [] signals = [] signal.signal(signal.SIGTERM, signal_handler) with open('kill.sh', 'w') as f: f.write(''' setsid bash -c "sleep 1; echo hello; setsid sleep 1313 & disown" & disown sleep .3 kill -TERM {} sleep .1 '''.format(os.getpid())) cmd = ['bash', 'kill.sh'] with pytest.raises(RuntimeError): pksubprocess.check_call_with_signals( cmd, output=o, msg=msg, recursive_kill=True, ) time.sleep(2) o.seek(0) actual = o.read() assert '' == actual, \ 'Expecting empty output "{}"'.format(actual) assert signal.SIGTERM in signals, \ '"SIGTERM" not in signals "{}"'.format(signals) assert 'error exit' in messages[1], \ '"error exit" not in messages[1] "{}"'.format(messages[1]) p = subprocess.check_output( ['ps', 'axfj'], stdin=open(os.devnull), stderr=subprocess.STDOUT, ) assert 'sleep 1313' not in p, \ 'sleep did not terminate: {}'.format(p)
def _run_madx(): pksubprocess.check_call_with_signals( ['madx', template.MADX_INPUT_FILE], msg=pkdlog, output=template.MADX_LOG_FILE, )