Example #1
0
    def init_callbacks(self):
        """
        Fill custom callbacks with callable objects provided in config.
        """
        config = self.config

        pre_publish_callbacks = config.get('pre_publish_callbacks', [])
        for callable_path in pre_publish_callbacks:
            callback = utils.namedAny(callable_path)
            self.pre_publish_callbacks.append(callback)

        post_publish_callbacks = config.get('post_publish_callbacks', [])
        for callable_path in post_publish_callbacks:
            callback = utils.namedAny(callable_path)
            self.post_publish_callbacks.append(callback)
Example #2
0
    def init_callbacks(self):
        """
        Fill custom callbacks with callable objects provided in config.
        """
        config = self.settings['config']
        pre_publish_callbacks = config.get('pre_publish_callbacks', [])

        for callable_path in pre_publish_callbacks:
            callback = utils.namedAny(callable_path)
            self.pre_publish_callbacks.append(callback)

        post_publish_callbacks = config.get('post_publish_callbacks', [])
        for callable_path in post_publish_callbacks:
            callback = utils.namedAny(callable_path)
            self.post_publish_callbacks.append(callback)
Example #3
0
    def init_structure(self):
        """
        Initialize structure manager using settings provided
        in configuration file.
        """
        custom_settings = self.settings["config"]
        structure_settings = custom_settings.get("structure", {})

        # detect and apply database storage module
        storage_backend = structure_settings.get("storage", "centrifuge.structure.sqlite.Storage")
        storage_backend_class = utils.namedAny(storage_backend)
        logger.info("Storage module: {0}".format(storage_backend))

        self.structure = Structure(self)
        storage = storage_backend_class(self.structure, structure_settings.get("settings", {}))
        self.structure.set_storage(storage)

        def run_periodic_structure_update():
            # update structure periodically from database. This is necessary to be sure
            # that application has actual and correct structure information. Structure
            # updates also triggered in real-time by message passing through control channel,
            # but in rare cases those update messages can be lost because of some kind of
            # network errors
            logger.info("Structure storage connected")
            self.structure.update()
            periodic_structure_update = tornado.ioloop.PeriodicCallback(
                self.structure.update, structure_settings.get("update_interval", 30) * 1000
            )
            periodic_structure_update.start()

        tornado.ioloop.IOLoop.instance().add_callback(partial(storage.connect, run_periodic_structure_update))
Example #4
0
 def init_state(self):
     """
     Initialize state manager (for presence/history data).
     """
     config = self.settings['config']
     state_config = config.get("state", {})
     if not state_config:
         # use base fake state
         logger.info("No State configured")
         self.state = State(self, fake=True)
     else:
         state_storage = state_config.get('storage', 'centrifuge.state.base.State')
         state_storage_class = utils.namedAny(state_storage)
         self.state = state_storage_class(self)
         tornado.ioloop.IOLoop.instance().add_callback(self.state.initialize)
Example #5
0
 def init_state(self):
     """
     Initialize state manager (for presence/history data).
     """
     config = self.settings['config']
     state_config = config.get("state", {})
     if not state_config:
         # use base fake state
         logger.info("No State configured")
         self.state = State(self, fake=True)
     else:
         state_storage = state_config.get('storage', 'centrifuge.state.base.State')
         state_storage_class = utils.namedAny(state_storage)
         self.state = state_storage_class(self)
         tornado.ioloop.IOLoop.instance().add_callback(self.state.initialize)
Example #6
0
def main():

    tornado.options.parse_command_line()

    try:
        custom_settings = json.load(open(options.config, 'r'))
    except IOError:
        logger.warning(
            "Application started without configuration file.\n"
            "This is normal only during development and if you\n"
            "want to use MongoDB as data storage.\n"
        )
        custom_settings = {}

    database_settings = custom_settings.get('storage', {})

    # detect and apply database storage module
    storage_module = database_settings.get(
        'module', 'centrifuge.storage.mongodb'
    )
    storage = utils.import_module(storage_module)

    ioloop_instance = tornado.ioloop.IOLoop.instance()

    settings = dict(
        cookie_secret=custom_settings.get("cookie_secret", "bad secret"),
        login_url="/auth",
        template_path=os.path.join(
            os.path.dirname(__file__),
            os.path.join("web/frontend", "templates")
        ),
        static_path=os.path.join(
            os.path.dirname(__file__),
            os.path.join("web/frontend", "static")
        ),
        xsrf_cookies=True,
        autoescape="xhtml_escape",
        debug=options.debug,
        options=custom_settings
    )

    try:
        app = Application(settings)
        server = tornado.httpserver.HTTPServer(app)
        server.listen(options.port)
    except Exception as e:
        return stop_running(str(e))

    # create unique uid for this application
    app.uid = uuid.uuid4().hex

    state = State(app)

    centrifuge.handlers.state = state
    centrifuge.web.handlers.state = state
    centrifuge.rpc.state = state

    state.set_storage(storage)

    def run_periodic_state_update():
        state.update()
        periodic_state_update = tornado.ioloop.PeriodicCallback(
            state.update, custom_settings.get('state_update_interval', 30000)
        )
        periodic_state_update.start()

    ioloop_instance.add_callback(
        functools.partial(
            storage.init_db,
            state,
            database_settings.get('settings', {}),
            run_periodic_state_update
        )
    )

    app.zmq_pub_sub_proxy = options.zmq_pub_sub_proxy

    context = zmq.Context()

    # create PUB socket to publish instance events into it
    publish_socket = context.socket(zmq.PUB)
    # do not try to send messages after closing
    publish_socket.setsockopt(zmq.LINGER, 0)

    if app.zmq_pub_sub_proxy:
        # application started with XPUB/XSUB proxy
        app.zmq_xsub = options.zmq_xsub
        publish_socket.connect(app.zmq_xsub)
    else:
        # application started without XPUB/XSUB proxy
        if options.zmq_pub_port_shift:
            # calculate zmq pub port number
            zmq_pub_port = options.port + options.zmq_pub_port_shift
        else:
            zmq_pub_port = options.zmq_pub_port

        app.zmq_pub_port = zmq_pub_port

        publish_socket.bind(
            "tcp://%s:%s" % (options.zmq_pub_listen, str(app.zmq_pub_port))
        )

    # wrap pub socket into ZeroMQ stream
    app.pub_stream = ZMQStream(publish_socket)

    # create SUB socket listening to all events from all app instances
    subscribe_socket = context.socket(zmq.SUB)

    if app.zmq_pub_sub_proxy:
        # application started with XPUB/XSUB proxy
        app.zmq_xpub = options.zmq_xpub
        subscribe_socket.connect(app.zmq_xpub)
    else:
        # application started without XPUB/XSUB proxy
        app.zmq_sub_address = options.zmq_sub_address
        for address in app.zmq_sub_address:
            subscribe_socket.connect(address)

    subscribe_socket.setsockopt_string(
        zmq.SUBSCRIBE,
        six.u(create_control_channel_name())
    )

    def listen_control_channel():
        # wrap sub socket into ZeroMQ stream and set its on_recv callback
        app.sub_stream = ZMQStream(subscribe_socket)
        handle = functools.partial(handle_control_message, app)
        app.sub_stream.on_recv(handle)

    ioloop_instance.add_callback(listen_control_channel)

    app.event_callbacks = []
    callbacks = custom_settings.get('event_callbacks', [])

    for callback in callbacks:
        event_callback = utils.namedAny(callback)
        app.event_callbacks.append(event_callback)

    if not hasattr(app, 'admin_connections'):
        # initialize dict to keep admin connections
        app.admin_connections = {}

    if not hasattr(app, 'connections'):
        # initialize dict to keep client's connections
        app.connections = {}

    if not hasattr(app, 'back_off'):
        # initialize dict to keep back-off information for projects
        app.back_off = {}

    logger.info("Application started")
    logger.info("Tornado port: {0}".format(options.port))
    if app.zmq_pub_sub_proxy:
        logger.info(
            "ZeroMQ XPUB: {0}, XSUB: {1}".format(
                app.zmq_xpub, app.zmq_xsub,
            )
        )
    else:
        logger.info(
            "ZeroMQ PUB - {0}; subscribed to {1}".format(
                app.zmq_pub_port, app.zmq_sub_address
            )
        )
    logger.info("Storage module: {0}".format(storage_module))

    # finally, let's go
    try:
        ioloop_instance.start()
    except KeyboardInterrupt:
        logger.info('interrupted')
    finally:
        # clean
        if hasattr(app, 'pub_stream'):
            app.pub_stream.close()
        if hasattr(app, 'sub_stream'):
            app.sub_stream.on_recv(None)
            app.sub_stream.close()
Example #7
0
    "name", default='', help="unique node name", type=str
)

define(
    "web", default='', help="path to web app directory", type=str
)

engine = os.environ.get('CENTRIFUGE_ENGINE')
if not engine or engine == 'memory':
    engine_class_path = 'centrifuge.engine.memory.Engine'
elif engine == "redis":
    engine_class_path = 'centrifuge.engine.redis.Engine'
else:
    engine_class_path = engine

engine_class = namedAny(engine_class_path)


tornado.options.parse_command_line()


def setup_logging_level(level):
    """
    Set logging level for Centrifuge logger according to command-line option provided
    """
    if level == 'none':
        return

    logger.setLevel(getattr(logging, level.upper()))

Example #8
0
define("port", default=8000, help="app port", type=int)

define("config", default='config.json', help="JSON config file", type=str)

define("name", default='', help="unique node name", type=str)

engine = os.environ.get('CENTRIFUGE_ENGINE')
if not engine or engine == 'memory':
    engine_class_path = 'centrifuge.engine.memory.Engine'
elif engine == "redis":
    engine_class_path = 'centrifuge.engine.redis.Engine'
else:
    engine_class_path = engine

engine_class = namedAny(engine_class_path)

storage = os.environ.get('CENTRIFUGE_STORAGE')
if not storage or storage == 'sqlite':
    storage_class_path = 'centrifuge.structure.sqlite.Storage'
elif storage == "file":
    storage_class_path = 'centrifuge.structure.file.Storage'
else:
    storage_class_path = storage

storage_class = namedAny(storage_class_path)

tornado.options.parse_command_line()


def setup_logging_level(level):
Example #9
0
)

define(
    "name", default='', help="unique node name", type=str
)


engine = os.environ.get('CENTRIFUGE_ENGINE')
if not engine or engine == 'memory':
    engine_class_path = 'centrifuge.engine.memory.Engine'
elif engine == "redis":
    engine_class_path = 'centrifuge.engine.redis.Engine'
else:
    engine_class_path = engine

engine_class = namedAny(engine_class_path)


storage = os.environ.get('CENTRIFUGE_STORAGE')
if not storage or storage == 'sqlite':
    storage_class_path = 'centrifuge.structure.sqlite.Storage'
elif storage == "file":
    storage_class_path = 'centrifuge.structure.file.Storage'
else:
    storage_class_path = storage

storage_class = namedAny(storage_class_path)


tornado.options.parse_command_line()
Example #10
0
define("config", default='config.json', help="JSON config file", type=str)

define("name", default='', help="unique node name", type=str)

define("web", default='', help="path to web app directory", type=str)

engine = os.environ.get('CENTRIFUGE_ENGINE')
if not engine or engine == 'memory':
    engine_class_path = 'centrifuge.engine.memory.Engine'
elif engine == "redis":
    engine_class_path = 'centrifuge.engine.redis.Engine'
else:
    engine_class_path = engine

engine_class = namedAny(engine_class_path)

tornado.options.parse_command_line()


def setup_logging_level(level):
    """
    Set logging level for Centrifuge logger according to command-line option provided
    """
    if level == 'none':
        return

    logger.setLevel(getattr(logging, level.upper()))


setup_logging_level(options.logging)
Example #11
0
def main():

    tornado.options.parse_command_line()

    try:
        custom_settings = json.load(open(options.config, "r"))
    except IOError:
        logger.warning(
            "Application started without configuration file.\n"
            "This is normal only during development and if you\n"
            "want to use MongoDB as data storage.\n"
        )
        custom_settings = {}

    database_settings = custom_settings.get("storage", {})

    # detect and apply database storage module
    storage_module = database_settings.get("module", "centrifuge.storage.mongodb")
    storage = utils.import_module(storage_module)

    ioloop_instance = tornado.ioloop.IOLoop.instance()

    settings = dict(
        cookie_secret=custom_settings.get("cookie_secret", "bad secret"),
        login_url="/auth",
        template_path=os.path.join(os.path.dirname(__file__), os.path.join("web/frontend", "templates")),
        static_path=os.path.join(os.path.dirname(__file__), os.path.join("web/frontend", "static")),
        xsrf_cookies=True,
        autoescape="xhtml_escape",
        debug=options.debug,
        options=custom_settings,
    )

    try:
        app = Application(settings)
        server = tornado.httpserver.HTTPServer(app)
        server.listen(options.port)
    except Exception as e:
        return stop_running(str(e))

    # create unique uid for this application
    app.uid = uuid.uuid4().hex

    state = State(app)

    centrifuge.handlers.state = state
    centrifuge.web.handlers.state = state
    centrifuge.rpc.state = state

    state.set_storage(storage)

    def run_periodic_state_update():
        state.update()
        periodic_state_update = tornado.ioloop.PeriodicCallback(
            state.update, custom_settings.get("state_update_interval", 30000)
        )
        periodic_state_update.start()

    ioloop_instance.add_callback(
        functools.partial(storage.init_db, state, database_settings.get("settings", {}), run_periodic_state_update)
    )

    app.zmq_pub_sub_proxy = options.zmq_pub_sub_proxy

    context = zmq.Context()

    # create PUB socket to publish instance events into it
    publish_socket = context.socket(zmq.PUB)
    # do not try to send messages after closing
    publish_socket.setsockopt(zmq.LINGER, 0)

    if app.zmq_pub_sub_proxy:
        # application started with XPUB/XSUB proxy
        app.zmq_xsub = options.zmq_xsub
        publish_socket.connect(app.zmq_xsub)
    else:
        # application started without XPUB/XSUB proxy
        if options.zmq_pub_port_shift:
            # calculate zmq pub port number
            zmq_pub_port = options.port + options.zmq_pub_port_shift
        else:
            zmq_pub_port = options.zmq_pub_port

        app.zmq_pub_port = zmq_pub_port

        publish_socket.bind("tcp://%s:%s" % (options.zmq_pub_listen, str(app.zmq_pub_port)))

    # wrap pub socket into ZeroMQ stream
    app.pub_stream = ZMQStream(publish_socket)

    # create SUB socket listening to all events from all app instances
    subscribe_socket = context.socket(zmq.SUB)

    if app.zmq_pub_sub_proxy:
        # application started with XPUB/XSUB proxy
        app.zmq_xpub = options.zmq_xpub
        subscribe_socket.connect(app.zmq_xpub)
    else:
        # application started without XPUB/XSUB proxy
        app.zmq_sub_address = options.zmq_sub_address
        for address in app.zmq_sub_address:
            subscribe_socket.connect(address)

    subscribe_socket.setsockopt_string(zmq.SUBSCRIBE, six.u(create_control_channel_name()))

    def listen_control_channel():
        # wrap sub socket into ZeroMQ stream and set its on_recv callback
        app.sub_stream = ZMQStream(subscribe_socket)
        handle = functools.partial(handle_control_message, app)
        app.sub_stream.on_recv(handle)

    ioloop_instance.add_callback(listen_control_channel)

    app.event_callbacks = []
    callbacks = custom_settings.get("event_callbacks", [])

    for callback in callbacks:
        event_callback = utils.namedAny(callback)
        app.event_callbacks.append(event_callback)

    if not hasattr(app, "admin_connections"):
        # initialize dict to keep admin connections
        app.admin_connections = {}

    if not hasattr(app, "connections"):
        # initialize dict to keep client's connections
        app.connections = {}

    if not hasattr(app, "back_off"):
        # initialize dict to keep back-off information for projects
        app.back_off = {}

    logger.info("Application started")
    logger.info("Tornado port: {0}".format(options.port))
    if app.zmq_pub_sub_proxy:
        logger.info("ZeroMQ XPUB: {0}, XSUB: {1}".format(app.zmq_xpub, app.zmq_xsub))
    else:
        logger.info("ZeroMQ PUB - {0}; subscribed to {1}".format(app.zmq_pub_port, app.zmq_sub_address))
    logger.info("Storage module: {0}".format(storage_module))

    # finally, let's go
    try:
        ioloop_instance.start()
    except KeyboardInterrupt:
        logger.info("interrupted")
    finally:
        # clean
        if hasattr(app, "pub_stream"):
            app.pub_stream.close()
        if hasattr(app, "sub_stream"):
            app.sub_stream.on_recv(None)
            app.sub_stream.close()