def init(app, simulation_db): """Convert route map to dispatchable callables Initializes `_uri_to_route` and adds a single flask route (`_dispatch`) to dispatch based on the map. Args: app (Flask): flask app """ if _uri_to_route: return from sirepo import feature_config for n in _REQUIRED_MODULES + tuple(sorted( feature_config.cfg().api_modules)): register_api_module(importlib.import_module('sirepo.' + n)) _init_uris(app, simulation_db, feature_config.cfg().sim_types) sirepo.http_request.init(simulation_db=simulation_db, ) sirepo.http_reply.init(simulation_db=simulation_db, ) sirepo.uri.init( http_reply=sirepo.http_reply, http_request=sirepo.http_request, simulation_db=simulation_db, uri_router=pkinspect.this_module(), )
def is_sim_type(sim_type): """Validate simulation type Args: sim_type (str): to check Returns: bool: true if is a sim_type """ return sim_type in feature_config.cfg().sim_types
def _validate_root_redirect_uris(uri_to_route, simulation_db): from sirepo import feature_config u = set(uri_to_route.keys()) t = feature_config.cfg().sim_types r = set(simulation_db.SCHEMA_COMMON.rootRedirectUri.keys()) i = u & r | u & t | r & t assert not i, f'rootRedirectUri, sim_types, and routes have overlapping uris={i}' for x in r: assert re.search(r'^[a-z]+$', x), \ f'rootRedirectUri={x} must consist of letters only'
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 write_status(status, run_dir): """Write status to simulation Args: status (str): pending, running, completed, canceled run_dir (py.path): where to write the file """ if not feature_config.cfg().job: pkio.atomic_write( run_dir.join(sirepo.job.RUNNER_STATUS_FILE), status.encode(), )
def user_create(login_callback): """Create a user and initialize the directory Returns: str: New user id """ uid = _random_id(user_dir_name())['id'] # Must logged in before calling simulation_dir login_callback(uid) for simulation_type in feature_config.cfg().sim_types: _create_lib_and_examples(simulation_type) return uid
def get_schema(sim_type): """Get the schema for `sim_type` If sim_type is None, it will return the schema for the first sim_type in `feature_config.cfg().sim_types` Args: sim_type (str): must be valid Returns: dict: Shared schem """ t = sirepo.template.assert_sim_type(sim_type) if sim_type is not None \ else feature_config.cfg().sim_types[0] if t in _SCHEMA_CACHE: return _SCHEMA_CACHE[t] schema = read_json(STATIC_FOLDER.join('json/{}-schema'.format(t))) pkcollections.mapping_merge(schema, SCHEMA_COMMON) pkcollections.mapping_merge( schema, PKDict(feature_config=feature_config.for_sim_type(t).pkupdate( job=feature_config.cfg().job, ), ), ) schema.simulationType = t _SCHEMA_CACHE[t] = schema #TODO(mvk): improve merging common and local schema _merge_dicts(schema.common.dynamicFiles, schema.dynamicFiles) schema.dynamicModules = _files_in_schema(schema.dynamicFiles) for item in [ 'appModes', 'constants', 'cookies', 'enum', 'notifications', 'localRoutes', 'model', 'view' ]: if item not in schema: schema[item] = PKDict() _merge_dicts(schema.common[item], schema[item]) _merge_subclasses(schema, item) srschema.validate(schema) return schema
def validate_sim_db_file_path(path, uid): import sirepo.job assert re.search( re.compile(r'^{}/{}/{}/({})/{}/[a-zA-Z0-9-_\.]{{1,128}}$'.format( sirepo.job.SIM_DB_FILE_URI, USER_ROOT_DIR, uid, '|'.join(feature_config.cfg().sim_types), _ID_PARTIAL_RE_STR, )), path, ), f'invalid path={path} or uid={uid}'
def user_create(): """Create a user and initialize the directory Returns: str: New user id """ uid = _random_id(user_path())['id'] for simulation_type in feature_config.cfg().sim_types: _create_lib_and_examples( simulation_type, uid=uid, ) return uid
def api_robotsTxt(): """Disallow the app (dev, prod) or / (alpha, beta)""" global _ROBOTS_TXT if not _ROBOTS_TXT: # We include dev so we can test if pkconfig.channel_in('prod', 'dev'): u = [ sirepo.uri.api('root', params={'path_info': x}) for x in sorted(feature_config.cfg().sim_types) ] else: u = ['/'] _ROBOTS_TXT = ''.join(['User-agent: *\n'] + ['Disallow: /{}\n'.format(x) for x in u], ) return flask.Response(_ROBOTS_TXT, mimetype='text/plain')
def audit_proprietary_lib_files(*uid): """Add/removes proprietary files based on a user's roles For example, add the Flash executable if user has the flash role. Args: *uid: Uid(s) of the user(s) to audit. If None all users will be audited. """ import py def _audit_user(uid, proprietary_sim_types): with auth.set_user(uid): for t in proprietary_sim_types: _link_or_unlink_proprietary_files( t, auth.check_user_has_role( auth.role_for_sim_type(t), raise_forbidden=False, ), ) def _link_or_unlink_proprietary_files(sim_type, should_link): d = proprietary_code_dir(sim_type) for e in simulation_db.examples(sim_type): b = sim_data.get_class(sim_type).proprietary_lib_file_basename(e) p = simulation_db.simulation_lib_dir(sim_type).join(b) if not should_link: pkio.unchecked_remove(p) continue try: p.mksymlinkto( d.join(b), absolute=False, ) except py.error.EEXIST: pass server.init() t = feature_config.cfg().proprietary_sim_types if not t: return for u in uid or auth_db.all_uids(): _audit_user(u, t)
def hack_nfs_write_status(status, run_dir): """Verify status file exists before writing. NFS doesn't propagate files immediately so there is a race condition when the celery worker starts. This file handles this case. Args: status (str): pending, running, completed, canceled run_dir (py.path): where to write the file """ if feature_config.cfg().job: return fn = run_dir.join(sirepo.job.RUNNER_STATUS_FILE) for i in range(cfg.nfs_tries): if fn.check(file=True): break time.sleep(cfg.nfs_sleep) # Try once always write_status(status, run_dir)
def create_examples(): """Adds missing app examples to all users. """ server.init() for d in pkio.sorted_glob(simulation_db.user_dir_name().join('*')): if _is_src_dir(d): continue uid = simulation_db.uid_from_dir_name(d) auth.set_user_for_utils(uid) for sim_type in feature_config.cfg().sim_types: simulation_db.verify_app_directory(sim_type) names = [ x.name for x in simulation_db.iterate_simulation_datafiles( sim_type, simulation_db.process_simulation_list, { 'simulation.isExample': True, }) ] for example in simulation_db.examples(sim_type): if example.models.simulation.name not in names: _create_example(example)
def create_examples(): """Adds missing app examples to all users""" import sirepo.auth_db import sirepo.server sirepo.server.init() for d in pkio.sorted_glob(simulation_db.user_path().join('*')): if _is_src_dir(d): continue; uid = simulation_db.uid_from_dir_name(d) with sirepo.auth_db.session_and_lock(), \ auth.set_user_outside_of_http_request(uid): for sim_type in feature_config.cfg().sim_types: simulation_db.verify_app_directory(sim_type) names = [x.name for x in simulation_db.iterate_simulation_datafiles( sim_type, simulation_db.process_simulation_list, { 'simulation.isExample': True, })] for example in simulation_db.examples(sim_type): if example.models.simulation.name not in names: _create_example(example)
import flask import importlib import os import re import sirepo.events import sirepo.sim_data import sirepo.srdb import sirepo.template import sirepo.uri import sirepo.util import urllib import werkzeug import werkzeug.exceptions #TODO(pjm): this import is required to work-around template loading in listSimulations, see #1151 if any(k in feature_config.cfg().sim_types for k in ('flash', 'rs4pi', 'radia', 'synergia', 'silas', 'warppba', 'warpvnd')): import h5py #: If google_tag_manager_id set, string to insert in landing pages for google analytics _google_tag_manager = None #: what to match in landing pages to insert `_google_tag_manager` _google_tag_manager_re = re.compile('(?=</head>)', flags=re.IGNORECASE) #: See sirepo.srunit SRUNIT_TEST_IN_REQUEST = 'srunit_test_in_request' #: Default file to serve on errors DEFAULT_ERROR_FILE = 'server-error.html'
def init_apis(app, *args, **kwargs): for e, _ in simulation_db.SCHEMA_COMMON['customErrors'].items(): app.register_error_handler(int(e), _handle_error) importlib.import_module('sirepo.' + ( 'job' if feature_config.cfg().job else 'runner')).init_by_server(app)