Source code for tvb.interfaces.rest.server.run

# -*- coding: utf-8 -*-
#
#
# TheVirtualBrain-Framework Package. This package holds all Data Management, and
# Web-UI helpful to run brain-simulations. To use it, you also need to download
# TheVirtualBrain-Scientific Package (for simulators). See content of the
# documentation-folder for more details. See also http://www.thevirtualbrain.org
#
# (c) 2012-2024, Baycrest Centre for Geriatric Care ("Baycrest") and others
#
# This program is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this
# program.  If not, see <http://www.gnu.org/licenses/>.
#
#
#   CITATION:
# When using The Virtual Brain for scientific publications, please cite it as explained here:
# https://www.thevirtualbrain.org/tvb/zwei/neuroscience-publications
#
#

import os
import sys
from flask import Flask
from flask_restx.apidoc import apidoc
from gevent.pywsgi import WSGIServer
from tvb.basic.logger.builder import get_logger
from tvb.basic.profile import TvbProfile
from tvb.config.init.initializer import initialize
from tvb.core.services.authorization import AuthorizationManager
from tvb.core.services.exceptions import InvalidSettingsException
from tvb.interfaces.rest.commons.strings import RestNamespace, RestLink, LinkPlaceholder, Strings
from tvb.interfaces.rest.server.decorators.encoders import CustomFlaskEncoder
from tvb.interfaces.rest.server.resources.datatype.datatype_resource import RetrieveDatatypeResource, \
    GetOperationsForDatatypeResource, GetExtraInfoForDatatypeResource, IsDataEncryptedResource
from tvb.interfaces.rest.server.resources.operation.operation_resource import GetOperationStatusResource, \
    GetOperationResultsResource, LaunchOperationResource
from tvb.interfaces.rest.server.resources.project.project_resource import GetOperationsInProjectResource, \
    GetDataInProjectResource, ProjectMembersResource
from tvb.interfaces.rest.server.resources.simulator.simulation_resource import FireSimulationResource
from tvb.interfaces.rest.server.resources.user.user_resource import LoginUserResource, GetProjectsListResource, \
    GetUsersResource, LinksResource
from tvb.interfaces.rest.server.rest_api import RestApi
from tvb.storage.storage_interface import StorageInterface
from werkzeug.middleware.proxy_fix import ProxyFix

TvbProfile.set_profile(TvbProfile.COMMAND_PROFILE)
CONFIG_EXISTS = not TvbProfile.is_first_run()
LOGGER = get_logger('tvb.interfaces.rest.server.run')
LOGGER.info("TVB application will be running using encoding: " + sys.getdefaultencoding())


[docs] def initialize_tvb_flask(): if not os.path.exists(TvbProfile.current.TVB_STORAGE): try: os.makedirs(TvbProfile.current.TVB_STORAGE) except Exception: sys.exit("You do not have enough rights to use TVB storage folder:" + str(TvbProfile.current.TVB_STORAGE)) try: initialize(skip_updates=True) except InvalidSettingsException as excep: LOGGER.exception(excep) sys.exit()
[docs] def build_path(namespace): return Strings.BASE_PATH.value + namespace.value
[docs] def initialize_flask(): if TvbProfile.current.web.REST_DEPLOY_CONTEXT: apidoc.url_prefix = TvbProfile.current.web.REST_DEPLOY_CONTEXT # creating the flask app app = Flask(__name__) app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1) app.json_encoder = CustomFlaskEncoder # creating an API object api = RestApi(app, prefix=TvbProfile.current.web.REST_DEPLOY_CONTEXT, title="Rest services for TVB", doc=TvbProfile.current.web.REST_DEPLOY_CONTEXT + "/doc/", version=TvbProfile.current.version.CURRENT_VERSION) # Users namespace name_space_users = api.namespace(build_path(RestNamespace.USERS), description="TVB-REST APIs for users management") name_space_users.add_resource(GetUsersResource, "/") name_space_users.add_resource(LoginUserResource, RestLink.LOGIN.compute_url()) name_space_users.add_resource(GetProjectsListResource, RestLink.PROJECTS.compute_url()) name_space_users.add_resource(LinksResource, RestLink.USEFUL_URLS.compute_url()) # Projects namespace name_space_projects = api.namespace(build_path(RestNamespace.PROJECTS), description="TVB-REST APIs for projects management") name_space_projects.add_resource(GetDataInProjectResource, RestLink.DATA_IN_PROJECT.compute_url( values={LinkPlaceholder.PROJECT_GID.value: "<string:project_gid>"})) name_space_projects.add_resource(GetOperationsInProjectResource, RestLink.OPERATIONS_IN_PROJECT.compute_url( values={LinkPlaceholder.PROJECT_GID.value: "<string:project_gid>"})) name_space_projects.add_resource(ProjectMembersResource, RestLink.PROJECT_MEMBERS.compute_url( values={LinkPlaceholder.PROJECT_GID.value: "<string:project_gid>"})) # Datatypes namepsace name_space_datatypes = api.namespace(build_path(RestNamespace.DATATYPES), description="TVB-REST APIs for datatypes management") name_space_datatypes.add_resource(RetrieveDatatypeResource, RestLink.GET_DATATYPE.compute_url( values={LinkPlaceholder.DATATYPE_GID.value: '<string:datatype_gid>'})) name_space_datatypes.add_resource(GetOperationsForDatatypeResource, RestLink.DATATYPE_OPERATIONS.compute_url( values={LinkPlaceholder.DATATYPE_GID.value: '<string:datatype_gid>'})) name_space_datatypes.add_resource(GetExtraInfoForDatatypeResource, RestLink.DATATYPE_EXTRA_INFO.compute_url( values={LinkPlaceholder.DATATYPE_GID.value: '<string:datatype_gid>'})) name_space_datatypes.add_resource(IsDataEncryptedResource, RestLink.IS_DATA_ENCRYPTED.compute_url()) # Operations namespace name_space_operations = api.namespace(build_path(RestNamespace.OPERATIONS), description="TVB-REST APIs for operations management") name_space_operations.add_resource(LaunchOperationResource, RestLink.LAUNCH_OPERATION.compute_url(values={ LinkPlaceholder.PROJECT_GID.value: '<string:project_gid>', LinkPlaceholder.ALG_MODULE.value: '<string:algorithm_module>', LinkPlaceholder.ALG_CLASSNAME.value: '<string:algorithm_classname>' })) name_space_operations.add_resource(GetOperationStatusResource, RestLink.OPERATION_STATUS.compute_url(values={ LinkPlaceholder.OPERATION_GID.value: '<string:operation_gid>' })) name_space_operations.add_resource(GetOperationResultsResource, RestLink.OPERATION_RESULTS.compute_url(values={ LinkPlaceholder.OPERATION_GID.value: '<string:operation_gid>' })) # Simulation namespace name_space_simulation = api.namespace(build_path(RestNamespace.SIMULATION), description="TVB-REST APIs for simulation management") name_space_simulation.add_resource(FireSimulationResource, RestLink.FIRE_SIMULATION.compute_url( values={LinkPlaceholder.PROJECT_GID.value: '<string:project_gid>'})) api.add_namespace(name_space_users) api.add_namespace(name_space_projects) api.add_namespace(name_space_datatypes) api.add_namespace(name_space_operations) api.add_namespace(name_space_simulation) if StorageInterface.encryption_enabled() and StorageInterface.app_encryption_handler(): storage_interface = StorageInterface() storage_interface.start() storage_interface.startup_cleanup() # Register keycloak authorization manager AuthorizationManager(TvbProfile.current.KEYCLOAK_CONFIG) http_server = WSGIServer(("0.0.0.0", TvbProfile.current.web.REST_PORT), app) http_server.serve_forever()
if __name__ == '__main__': # Prepare parameters and fire Flask if not TvbProfile.current.KEYCLOAK_CONFIG: LOGGER.info("REST server will not start because KEYCLOAK CONFIG path is not set.") elif not os.path.exists(TvbProfile.current.KEYCLOAK_CONFIG): LOGGER.warning("Cannot start REST server because the KEYCLOAK CONFIG file {} does not exist.".format( TvbProfile.current.KEYCLOAK_CONFIG)) elif CONFIG_EXISTS: LOGGER.info("Starting Flask server with REST API...") initialize_tvb_flask() initialize_flask() else: LOGGER.info("We will not start REST until some tvb.config file exists on this machine...")