Beispiel #1
0
def server(db, request):
    """
    Require a CherryPy embedded server.

    Provides a started CherryPy embedded server with a request method for performing
    local requests against it. Note: this fixture requires the db fixture.
    """
    # The event daemon cannot be restarted since it is a threading.Thread object, however
    # all references to girder.events.daemon are a singular global daemon due to its side
    # effect on import. We have to hack around this by creating a unique event daemon
    # each time we startup the server and assigning it to the global.
    import girder.events
    from girder.api import docs
    from girder.constants import SettingKey
    from girder.models.setting import Setting
    from girder.utility import plugin_utilities
    from girder.utility.server import setup as setupServer

    oldPluginDir = plugin_utilities.getPluginDir

    girder.events.daemon = girder.events.AsyncEventsThread()

    enabledPlugins = []
    testPluginMarkers = request.node.get_marker('testPlugin')
    if testPluginMarkers is not None:
        for testPluginMarker in testPluginMarkers:
            pluginName = testPluginMarker.args[0]
            enabledPlugins.append(pluginName)

        # testFilePath is a py.path.local object that we *assume* lives in 'test/',
        # with 'test/test_plugins' nearby
        testFilePath = request.node.fspath
        testPluginsPath = testFilePath.dirpath('test_plugins').strpath
        plugin_utilities.getPluginDir = mock.Mock(return_value=testPluginsPath)

        Setting().set(SettingKey.PLUGINS_ENABLED, enabledPlugins)

    server = setupServer(test=True, plugins=enabledPlugins)
    server.request = restRequest

    cherrypy.server.unsubscribe()
    cherrypy.config.update({'environment': 'embedded',
                            'log.screen': False,
                            'request.throw_errors': True})
    cherrypy.engine.start()

    yield server

    cherrypy.engine.unsubscribe('start', girder.events.daemon.start)
    cherrypy.engine.unsubscribe('stop', girder.events.daemon.stop)
    cherrypy.engine.stop()
    cherrypy.engine.exit()
    cherrypy.tree.apps = {}
    plugin_utilities.getPluginDir = oldPluginDir
    plugin_utilities.getPluginWebroots().clear()
    plugin_utilities.getPluginFailureInfo().clear()
    docs.routes.clear()
Beispiel #2
0
def loadRouteTable(reconcileRoutes=False):
    """
    Retrieves the route table from Girder and reconciles the state of it with the current
    application state.

    Reconciliation ensures that every enabled plugin has a route by assigning default routes for
    plugins that have none, such as newly-enabled plugins.

    :returns: The non empty routes (as a dict of name -> route) to be mounted by CherryPy
              during Girder's setup phase.
    """
    pluginWebroots = plugin_utilities.getPluginWebroots()
    setting = model_importer.ModelImporter().model('setting')
    routeTable = setting.get(constants.SettingKey.ROUTE_TABLE)

    def reconcileRouteTable(routeTable):
        hasChanged = False

        for name in pluginWebroots.keys():
            if name not in routeTable:
                routeTable[name] = os.path.join('/', name)
                hasChanged = True

        if hasChanged:
            setting.set(constants.SettingKey.ROUTE_TABLE, routeTable)

        return routeTable

    if reconcileRoutes:
        routeTable = reconcileRouteTable(routeTable)

    return {
        name: route
        for (name, route) in six.viewitems(routeTable) if route
    }
Beispiel #3
0
def loadRouteTable(reconcileRoutes=False):
    """
    Retrieves the route table from Girder and reconciles the state of it with the current
    application state.

    Reconciliation ensures that every enabled plugin has a route by assigning default routes for
    plugins that have none, such as newly-enabled plugins.

    :returns: The non empty routes (as a dict of name -> route) to be mounted by CherryPy
              during Girder's setup phase.
    """
    pluginWebroots = plugin_utilities.getPluginWebroots()
    setting = model_importer.ModelImporter().model('setting')
    routeTable = setting.get(constants.SettingKey.ROUTE_TABLE)

    def reconcileRouteTable(routeTable):
        hasChanged = False

        for name in pluginWebroots.keys():
            if name not in routeTable:
                routeTable[name] = os.path.join('/', name)
                hasChanged = True

        if hasChanged:
            setting.set(constants.SettingKey.ROUTE_TABLE, routeTable)

        return routeTable

    if reconcileRoutes:
        routeTable = reconcileRouteTable(routeTable)

    return {name: route for (name, route) in six.viewitems(routeTable) if route}
Beispiel #4
0
def setup(test=False, plugins=None, curConfig=None):
    """
    Configure and mount the Girder server and plugins under the
    appropriate routes.

    See ROUTE_TABLE setting.

    :param test: Whether to start in test mode.
    :param plugins: List of plugins to enable.
    :param curConfig: The config object to update.
    """
    logStdoutStderr()

    pluginWebroots = plugin_utilities.getPluginWebroots()
    girderWebroot, appconf = configureServer(test, plugins, curConfig)
    routeTable = loadRouteTable(reconcileRoutes=True)

    # Mount Girder
    application = cherrypy.tree.mount(
        girderWebroot, str(routeTable[constants.GIRDER_ROUTE_ID]), appconf)

    # Mount static files
    cherrypy.tree.mount(
        None, routeTable[constants.GIRDER_STATIC_ROUTE_ID], {
            '/': {
                'tools.staticdir.on':
                True,
                'tools.staticdir.dir':
                os.path.join(constants.STATIC_ROOT_DIR, 'clients/web/static'),
                'request.show_tracebacks':
                appconf['/']['request.show_tracebacks'],
                'response.headers.server':
                'Girder %s' % __version__,
                'error_page.default':
                _errorDefault
            }
        })

    # Mount API (special case)
    # The API is always mounted at /api AND at api relative to the Girder root
    cherrypy.tree.mount(girderWebroot.api, '/api', appconf)

    # Mount everything else in the routeTable
    for (name, route) in six.viewitems(routeTable):
        if name != constants.GIRDER_ROUTE_ID and name in pluginWebroots:
            cherrypy.tree.mount(pluginWebroots[name], route, appconf)

    if test:
        application.merge({'server': {'mode': 'testing'}})

    return application
Beispiel #5
0
def loadRouteTable(reconcileRoutes=False):
    """
    Retrieves the route table from Girder and reconciles the state of it with the current
    application state.

    Reconciliation deals with 2 scenarios:

    1. A plugin is no longer active (by being disabled or removed) and the route for the
       plugin needs to be removed.
    2. A webroot was added (a new plugin was enabled) and a default route needs to be added.

    :returns: The non empty routes (as a dict of name -> route) to be mounted by CherryPy
              during Girder's setup phase.
    """
    pluginWebroots = plugin_utilities.getPluginWebroots()
    setting = model_importer.ModelImporter().model('setting')
    routeTable = setting.get(constants.SettingKey.ROUTE_TABLE)
    reservedRoutes = (constants.GIRDER_ROUTE_ID,
                      constants.GIRDER_STATIC_ROUTE_ID)

    def reconcileRouteTable(routeTable):
        hasChanged = False

        # GIRDER_ROUTE_ID is a special route, which can't be removed
        for name in routeTable.keys():
            if name not in reservedRoutes and name not in pluginWebroots:
                del routeTable[name]
                hasChanged = True

        for name in pluginWebroots.keys():
            if name not in routeTable:
                routeTable[name] = os.path.join('/', name)
                hasChanged = True

        if hasChanged:
            setting.set(constants.SettingKey.ROUTE_TABLE, routeTable)

        return routeTable

    if reconcileRoutes:
        routeTable = reconcileRouteTable(routeTable)

    return {
        name: route
        for (name, route) in six.viewitems(routeTable) if route
    }
Beispiel #6
0
def setup(test=False, plugins=None, curConfig=None):
    """
    Configure and mount the Girder server and plugins under the
    appropriate routes.

    See ROUTE_TABLE setting.

    :param test: Whether to start in test mode.
    :param plugins: List of plugins to enable.
    :param curConfig: The config object to update.
    """
    logStdoutStderr()

    pluginWebroots = plugin_utilities.getPluginWebroots()
    girderWebroot, appconf = configureServer(test, plugins, curConfig)
    routeTable = loadRouteTable(reconcileRoutes=True)

    # Mount Girder
    application = cherrypy.tree.mount(girderWebroot,
                                      str(routeTable[constants.GIRDER_ROUTE_ID]), appconf)

    # Mount static files
    cherrypy.tree.mount(None, routeTable[constants.GIRDER_STATIC_ROUTE_ID],
                        {'/':
                         {'tools.staticdir.on': True,
                          'tools.staticdir.dir': os.path.join(constants.STATIC_ROOT_DIR,
                                                              'clients/web/static'),
                          'request.show_tracebacks': appconf['/']['request.show_tracebacks'],
                          'response.headers.server': 'Girder %s' % __version__,
                          'error_page.default': _errorDefault}})

    # Mount API (special case)
    # The API is always mounted at /api AND at api relative to the Girder root
    cherrypy.tree.mount(girderWebroot.api, '/api', appconf)

    # Mount everything else in the routeTable
    for (name, route) in six.viewitems(routeTable):
        if name != constants.GIRDER_ROUTE_ID and name in pluginWebroots:
            cherrypy.tree.mount(pluginWebroots[name], route, appconf)

    if test:
        application.merge({'server': {'mode': 'testing'}})

    return application