def _validate_serial(data): """Verify serial in data validates Args: data (dict): request with serial and possibly models Returns: object: None if all ok, or json response if invalid """ res = simulation_db.validate_serial(data) if not res: return None return http_reply.gen_json({ 'state': 'error', 'error': 'invalidSerial', 'simulationData': res, })
def api_getApplicationData(filename=None): """Get some data from the template Args: filename (str): if supplied, result is file attachment Returns: response: may be a file or JSON """ req = http_request.parse_post(template=True, filename=filename or None) with simulation_db.tmp_dir() as d: res = req.template.get_application_data(req.req_data, tmp_dir=d) if 'filename' in req: assert isinstance(res, pkconst.PY_PATH_LOCAL_TYPE), \ '{}: template did not return a file'.format(res) return http_reply.gen_file_as_attachment(res, filename=req.filename) return http_reply.gen_json(res)
def api_simulationFrame(frame_id): #TODO(robnagler) startTime is reportParametersHash; need version on URL and/or param names in URL keys = ['simulationType', 'simulationId', 'modelName', 'animationArgs', 'frameIndex', 'startTime'] data = dict(zip(keys, frame_id.split('*'))) template = sirepo.template.import_module(data) data['report'] = template.get_animation_name(data) run_dir = simulation_db.simulation_run_dir(data) model_data = simulation_db.read_json(run_dir.join(template_common.INPUT_BASE_NAME)) frame = template.get_simulation_frame(run_dir, data, model_data) resp = http_reply.gen_json(frame) if 'error' not in frame and template.WANT_BROWSER_FRAME_CACHE: now = datetime.datetime.utcnow() expires = now + datetime.timedelta(365) resp.headers['Cache-Control'] = 'public, max-age=31536000' resp.headers['Expires'] = expires.strftime("%a, %d %b %Y %H:%M:%S GMT") resp.headers['Last-Modified'] = now.strftime("%a, %d %b %Y %H:%M:%S GMT") else: _no_cache(resp) return resp
def api_importFile(simulation_type=None): """ Args: simulation_type (str): which simulation type Params: file: file data folder: where to import to """ import sirepo.importer error = None f = None try: template = simulation_type and sirepo.template.import_module(simulation_type) f = flask.request.files.get('file') assert f, \ ValueError('must supply a file') if pkio.has_file_extension(f.filename, 'json'): data = sirepo.importer.read_json(f.read(), template) #TODO(pjm): need a separate URI interface to importer, added exception for rs4pi for now # (dicom input is normally a zip file) elif pkio.has_file_extension(f.filename, 'zip') and simulation_type != 'rs4pi': data = sirepo.importer.read_zip(f.stream, template) else: assert simulation_type, \ 'simulation_type is required param for non-zip|json imports' assert hasattr(template, 'import_file'), \ ValueError('Only zip files are supported') data = template.import_file( flask.request, simulation_db.simulation_lib_dir(simulation_type), simulation_db.tmp_dir(), ) #TODO(robnagler) need to validate folder data.models.simulation.folder = flask.request.form['folder'] data.models.simulation.isExample = False return _save_new_and_reply(data) except Exception as e: pkdlog('{}: exception: {}', f and f.filename, pkdexc()) error = str(e.message) if hasattr(e, 'message') else str(e) return http_reply.gen_json({ 'error': error if error else 'An unknown error occurred', })
def api_runCancel(): data = _parse_data_input() jid = simulation_db.job_id(data) # TODO(robnagler) need to have a way of listing jobs # Don't bother with cache_hit check. We don't have any way of canceling # if the parameters don't match so for now, always kill. #TODO(robnagler) mutex required if runner.job_is_processing(jid): run_dir = simulation_db.simulation_run_dir(data) # Write first, since results are write once, and we want to # indicate the cancel instead of the termination error that # will happen as a result of the kill. simulation_db.write_result({'state': 'canceled'}, run_dir=run_dir) runner.job_kill(jid) # TODO(robnagler) should really be inside the template (t.cancel_simulation()?) # the last frame file may not be finished, remove it t = sirepo.template.import_module(data) t.remove_last_frame(run_dir) # Always true from the client's perspective return http_reply.gen_json({'state': 'canceled'})
def api_getApplicationData(filename=None): """Get some data from the template Args: filename (str): if supplied, result is file attachment Returns: response: may be a file or JSON """ req = http_request.parse_post(template=True, filename=filename or None) with simulation_db.tmp_dir() as d: assert 'method' in req.req_data res = req.template.get_application_data(req.req_data, tmp_dir=d) assert res != None, f'unhandled application data method: {req.req_data.method}' if 'filename' in req and isinstance(res, pkconst.PY_PATH_LOCAL_TYPE): return http_reply.gen_file_as_attachment( res, filename=req.filename, content_type=req.req_data.get('contentType', None)) return http_reply.gen_json(res)
def api_getApplicationData(filename=''): """Get some data from the template Args: filename (str): if supplied, result is file attachment Returns: response: may be a file or JSON """ data = _parse_data_input() res = sirepo.template.import_module(data).get_application_data(data) if filename: assert isinstance(res, _PY_PATH_LOCAL_CLASS), \ '{}: template did not return a file'.format(res) return flask.send_file( str(res), mimetype='application/octet-stream', as_attachment=True, attachment_filename=filename, ) return http_reply.gen_json(res)
def api_simulationFrame(frame_id): #TODO(robnagler) startTime is reportParametersHash; need version on URL and/or param names in URL keys = [ 'simulationType', 'simulationId', 'modelName', 'animationArgs', 'frameIndex', 'startTime' ] data = dict(zip(keys, frame_id.split('*'))) template = sirepo.template.import_module(data) data['report'] = template.get_animation_name(data) run_dir = simulation_db.simulation_run_dir(data) model_data = simulation_db.read_json( run_dir.join(template_common.INPUT_BASE_NAME)) if feature_config.cfg.runner_daemon: # XX TODO: it would be better if the frontend passed the jhash to this # call. Since it doesn't, we have to read it out of the run_dir, which # creates a race condition -- we might return a frame from a different # version of the report than the one the frontend expects. jhash = template_common.report_parameters_hash(model_data) frame = runner_client.run_extract_job( run_dir, jhash, 'get_simulation_frame', data, ) else: frame = template.get_simulation_frame(run_dir, data, model_data) resp = http_reply.gen_json(frame) if 'error' not in frame and template.WANT_BROWSER_FRAME_CACHE: now = datetime.datetime.utcnow() expires = now + datetime.timedelta(365) resp.headers['Cache-Control'] = 'public, max-age=31536000' resp.headers['Expires'] = expires.strftime("%a, %d %b %Y %H:%M:%S GMT") resp.headers['Last-Modified'] = now.strftime( "%a, %d %b %Y %H:%M:%S GMT") else: http_reply.headers_for_no_cache(resp) return resp
def api_simulationSchema(): sim_type = sirepo.template.assert_sim_type( flask.request.form['simulationType']) return http_reply.gen_json(simulation_db.get_schema(sim_type))
def api_runStatus(): data = _parse_data_input() return http_reply.gen_json(_simulation_run_status(data))
def api_simulationSchema(): return http_reply.gen_json( simulation_db.get_schema( http_request.parse_params( type=flask.request.form['simulationType'], ).type, ), )
def api_importFile(simulation_type): """ Args: simulation_type (str): which simulation type Params: file: file data folder: where to import to """ import sirepo.importer error = None f = None try: f = flask.request.files.get('file') if not f: raise sirepo.util.Error('must supply a file') req = http_request.parse_params( filename=f.filename, folder=flask.request.form.get('folder'), id=flask.request.form.get('simulationId'), template=True, type=simulation_type, ) req.file_stream = f.stream req.import_file_arguments = flask.request.form.get('arguments', '') def s(data): data.models.simulation.folder = req.folder data.models.simulation.isExample = False return _save_new_and_reply(data) if pkio.has_file_extension(req.filename, 'json'): data = sirepo.importer.read_json(req.file_stream.read(), req.type) #TODO(pjm): need a separate URI interface to importer, added exception for rs4pi for now # (dicom input is normally a zip file) elif pkio.has_file_extension(req.filename, 'zip') and req.type != 'rs4pi': data = sirepo.importer.read_zip(req.file_stream.read(), sim_type=req.type) else: if not hasattr(req.template, 'import_file'): raise sirepo.util.Error('Only zip files are supported') with simulation_db.tmp_dir() as d: data = req.template.import_file(req, tmp_dir=d, reply_op=s) if 'error' in data: return http_reply.gen_json(data) return s(data) except werkzeug.exceptions.HTTPException: raise except sirepo.util.Reply: raise except Exception as e: pkdlog('{}: exception: {}', f and f.filename, pkdexc()) #TODO(robnagler) security issue here. Really don't want to report errors to user if hasattr(e, 'args'): if len(e.args) == 1: error = str(e.args[0]) else: error = str(e.args) else: error = str(e) return http_reply.gen_json({ 'error': error if error else 'An unknown error occurred', })
def api_listFiles(simulation_type, simulation_id, file_type): #TODO(pjm): simulation_id is an unused argument req = http_request.parse_params(type=simulation_type, file_type=file_type) return http_reply.gen_json( req.sim_data.lib_file_names_for_type(req.file_type), )
def api_runStatus(): return http_reply.gen_json( _simulation_run_status( http_request.parse_post(id=True, model=True, check_sim_exists=True), ), )