Пример #1
0
def run_command_start(options):
   """
   Subcommand "crossbar start".
   """
   ## start Twisted logging
   ##
   log.startLogging(sys.stderr)

   log.msg("Crossbar.io {} node starting".format(crossbar.__version__))

   ## we use an Autobahn utility to import the "best" available Twisted reactor
   ##
   reactor = install_reactor(options.reactor, options.debug)

   #if options.debug:
   #   print("Running on reactor {}".format(reactor))

   ## create and start Crossbar.io node
   ##
   node = Node(reactor, options.cbdir, options.debug)
   node.start()

   ## enter event loop
   ##
   reactor.run()
Пример #2
0
def main():
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor()

    observatory.start_logging(10)
    plugins = [
        "sputnik.webserver.plugins.authz.default.DefaultPermissions",
        "sputnik.webserver.plugins.authn.anonymous.AnonymousLogin",
        "sputnik.webserver.plugins.authn.ip.IPFilter",
        "sputnik.webserver.plugins.authn.cookie.CookieLogin",
        "sputnik.webserver.plugins.authn.wampcra.WAMPCRALogin",
        "sputnik.webserver.plugins.authn.totp.TOTPVerification",
        "sputnik.webserver.plugins.db.mem.InMemoryDatabase",
        "sputnik.webserver.plugins.db.postgres.PostgresDatabase",
        "sputnik.webserver.plugins.backend.administrator.AdministratorProxy",
        "sputnik.webserver.plugins.backend.accountant.AccountantProxy",
        "sputnik.webserver.plugins.backend.cashier.CashierProxy",
        "sputnik.webserver.plugins.backend.alerts.AlertsProxy",
        "sputnik.webserver.plugins.rpc.registrar.RegistrarService",
        "sputnik.webserver.plugins.rpc.token.TokenService",
        "sputnik.webserver.plugins.rpc.info.InfoService",
        "sputnik.webserver.plugins.rpc.market.MarketService",
        "sputnik.webserver.plugins.rpc.private.PrivateService",
        "sputnik.webserver.plugins.rpc.trader.TraderService",
        "sputnik.webserver.plugins.feeds.market.MarketAnnouncer",
        "sputnik.webserver.plugins.feeds.user.UserAnnouncer",
        "sputnik.webserver.plugins.receiver.accountant.AccountantReceiver",
        "sputnik.webserver.plugins.receiver.engine.EngineReceiver",
        "sputnik.webserver.plugins.receiver.administrator.AdministratorReceiver",
        "sputnik.webserver.rest.RESTProxy"
    ]
    plugin.run_with_plugins(reactor, plugins, run, reactor)
Пример #3
0
def start_server():
    logger.info('Running on reactor.\nInfo:wsurl=%s, tcpurl=%s', CONF.wsurl,
                CONF.websocket)
    reactor = choosereactor.install_reactor()
    wsfactory = WSServerFactory(CONF.wsurl)
    wsserver = endpoints.serverFromString(reactor, CONF.websocket)

    task.LoopingCall(ws.instructions.server.check_heartbeat,
                     CONNECTS).start(15)
    task.LoopingCall(ws.instructions.common.ping_mysql).start(15)
    wsserver.listen(wsfactory)
    reactor.run()
Пример #4
0
def run_command_start(options):
    """
   Subcommand "crossbar start".
   """
    ## start Twisted logging
    ##
    if not options.logdir:
        logfd = sys.stderr
    else:
        from twisted.python.logfile import DailyLogFile
        logfd = DailyLogFile.fromFullPath(
            os.path.join(options.logdir, 'node.log'))

    from crossbar.twisted.processutil import DefaultSystemFileLogObserver
    flo = DefaultSystemFileLogObserver(logfd,
                                       system="{:<10} {:>6}".format(
                                           "Controller", os.getpid()))
    log.startLoggingWithObserver(flo.emit)

    log.msg("=" * 30 + " Crossbar.io " + "=" * 30 + "\n")

    import crossbar
    log.msg("Crossbar.io {} starting".format(crossbar.__version__))

    ## we use an Autobahn utility to import the "best" available Twisted reactor
    ##
    reactor = install_reactor(options.reactor, options.debug)

    from twisted.python.reflect import qual
    log.msg("Running on {} using {} reactor".format(
        platform.python_implementation(),
        qual(reactor.__class__).split('.')[-1]))
    log.msg("Starting from node directory {}".format(options.cbdir))

    ## create and start Crossbar.io node
    ##
    from crossbar.controller.node import Node
    node = Node(reactor, options)
    node.start()

    try:
        log.msg("Entering reactor event loop ...")
        reactor.run()
    except Exception as e:
        log.msg("Could not start reactor: {0}".format(e))
Пример #5
0
def start_client():
    logger.info('start_client')
    host, port, key = ws.dbapi.blocking_get_sync_host_port_key()
    CLIENT['host'] = host
    CLIENT['port'] = port
    CLIENT['key'] = key
    wsurl = 'ws://%s:%s/ws/sync' % (host, port)
    reactor = choosereactor.install_reactor()
    logger.info('Running on reactor. Upstream:wsurl=%s', wsurl)
    wsfactory = WSClientFactory(wsurl)
    task.LoopingCall(ws.instructions.client.periodical_sync_data,
                     CLIENT).start(settings.DEBUG and 15 or 180)  # 3min
    task.LoopingCall(ws.instructions.client.periodical_sync_cache,
                     CLIENT).start(15)
    task.LoopingCall(ws.instructions.client.periodical_sync_misc,
                     CLIENT).start(settings.DEBUG and 15 or 1800)  # 30min
    websocket.connectWS(wsfactory)
    reactor.run()
Пример #6
0
def run_command_start(options):
   """
   Subcommand "crossbar start".
   """
   ## start Twisted logging
   ##
   if not options.logdir:
      logfd = sys.stderr
   else:
      from twisted.python.logfile import DailyLogFile
      logfd = DailyLogFile.fromFullPath(os.path.join(options.logdir, 'node.log'))

   from crossbar.twisted.processutil import DefaultSystemFileLogObserver
   flo = DefaultSystemFileLogObserver(logfd, system = "{:<10} {:>6}".format("Controller", os.getpid()))
   log.startLoggingWithObserver(flo.emit)

   log.msg("=" * 30 + " Crossbar.io " + "=" * 30 + "\n")

   import crossbar
   log.msg("Crossbar.io {} starting".format(crossbar.__version__))

   ## we use an Autobahn utility to import the "best" available Twisted reactor
   ##
   reactor = install_reactor(options.reactor, options.debug)

   from twisted.python.reflect import qual
   log.msg("Running on {} using {} reactor".format(platform.python_implementation(), qual(reactor.__class__).split('.')[-1]))
   log.msg("Starting from node directory {}".format(options.cbdir))

   ## create and start Crossbar.io node
   ##
   from crossbar.controller.node import Node
   node = Node(reactor, options)
   node.start()

   try:
      log.msg("Entering reactor event loop ...")
      reactor.run()
   except Exception as e:
      log.msg("Could not start reactor: {0}".format(e))
Пример #7
0
def run_command_start(options):
    """
   Subcommand "crossbar start".
   """
    ## start Twisted logging
    ##
    if not options.logdir:
        logfd = sys.stderr
    else:
        from twisted.python.logfile import DailyLogFile

        logfd = DailyLogFile.fromFullPath(os.path.join(options.logdir, "node.log"))

    from crossbar.twisted.process import DefaultSystemFileLogObserver

    flo = DefaultSystemFileLogObserver(logfd, system="{:<10} {:>6}".format("Controller", os.getpid()))
    log.startLoggingWithObserver(flo.emit)

    log.msg("=" * 30 + " Crossbar.io " + "=" * 30 + "\n")

    log.msg("Crossbar.io {} node starting".format(crossbar.__version__))

    ## we use an Autobahn utility to import the "best" available Twisted reactor
    ##
    reactor = install_reactor(options.reactor, options.debug)

    # if options.debug:
    #   print("Running on reactor {}".format(reactor))

    ## create and start Crossbar.io node
    ##
    node = Node(reactor, options)
    node.start()

    ## enter event loop
    ##
    reactor.run()
Пример #8
0
    def __init__(self, debug = '0'):

        self.debug = debug

        log.startLogging(sys.stdout)

        ## we use an Autobahn utility to install the "best" available Twisted reactor
        ##
        from autobahn.twisted.choosereactor import install_reactor
        self.reactor = install_reactor()
        print("Running on reactor {}".format(self.reactor))


        ## create a WAMP router factory
        ##
        from autobahn.twisted.wamp import RouterFactory
        self.router_factory = RouterFactory()


        ## create a WAMP router session factory
        ##
        from autobahn.twisted.wamp import RouterSessionFactory
        self.session_factory = RouterSessionFactory(self.router_factory)


        ## Add embedded WAMP application sessions to the router
        ##
        from core.rpc import MyBackendComponent
        component_config = types.ComponentConfig(realm = "realm1")
        component_session = MyBackendComponent(component_config)
        self.session_factory.add(component_session)

        ## create a WAMP-over-WebSocket transport server factory
        ##
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        self.transport_factory = WampWebSocketServerFactory(self.session_factory, debug = self.debug)
        self.transport_factory.setProtocolOptions(failByDrop = False)
Пример #9
0
def run_command_version(options):
    """
    Subcommand "crossbar version".
    """
    reactor = install_reactor(options.reactor, options.debug)

    # Python
    #
    py_ver = '.'.join([str(x) for x in list(sys.version_info[:3])])
    if options.debug:
        py_ver += " [%s]" % sys.version.replace('\n', ' ')

    if 'pypy_version_info' in sys.__dict__:
        py_ver_detail = "{}-{}".format(
            platform.python_implementation(),
            '.'.join(str(x) for x in sys.pypy_version_info[:3]))
    else:
        py_ver_detail = platform.python_implementation()

    # Twisted / Reactor
    #
    tx_ver = "%s-%s" % (pkg_resources.require("Twisted")[0].version,
                        reactor.__class__.__name__)
    if options.debug:
        tx_ver += " [%s]" % qual(reactor.__class__)

    # Autobahn
    #
    from autobahn.websocket.protocol import WebSocketProtocol
    ab_ver = pkg_resources.require("autobahn")[0].version
    if options.debug:
        ab_ver += " [%s]" % qual(WebSocketProtocol)

    # UTF8 Validator
    #
    from autobahn.websocket.utf8validator import Utf8Validator
    s = qual(Utf8Validator)
    if 'wsaccel' in s:
        utf8_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
    elif s.startswith('autobahn'):
        utf8_ver = 'autobahn'
    else:
        # could not detect UTF8 validator type/version
        utf8_ver = '?'
    if options.debug:
        utf8_ver += " [%s]" % qual(Utf8Validator)

    # XOR Masker
    #
    from autobahn.websocket.xormasker import XorMaskerNull
    s = qual(XorMaskerNull)
    if 'wsaccel' in s:
        xor_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
    elif s.startswith('autobahn'):
        xor_ver = 'autobahn'
    else:
        # could not detect XOR masker type/version
        xor_ver = '?'
    if options.debug:
        xor_ver += " [%s]" % qual(XorMaskerNull)

    # JSON Serializer
    #
    from autobahn.wamp.serializer import JsonObjectSerializer
    s = str(JsonObjectSerializer.JSON_MODULE)
    if 'ujson' in s:
        json_ver = 'ujson-%s' % pkg_resources.require('ujson')[0].version
    else:
        json_ver = 'stdlib'

    # MsgPack Serializer
    #
    try:
        import msgpack  # noqa
        msgpack_ver = 'msgpack-python-%s' % pkg_resources.require(
            'msgpack-python')[0].version
    except ImportError:
        msgpack_ver = '-'

    for line in BANNER.splitlines():
        print(click.style(("{:>40}").format(line), fg='yellow', bold=True))

    print("Crossbar.io        : {0}".format(
        click.style(crossbar.__version__, fg='yellow', bold=True)))
    print("  Autobahn         : {0}".format(
        click.style(ab_ver, fg='yellow', bold=True)))
    print("    UTF8 Validator : {0}".format(
        click.style(utf8_ver, fg='yellow', bold=True)))
    print("    XOR Masker     : {0}".format(
        click.style(xor_ver, fg='yellow', bold=True)))
    print("    JSON Codec     : {0}".format(
        click.style(json_ver, fg='yellow', bold=True)))
    print("    MsgPack Codec  : {0}".format(
        click.style(msgpack_ver, fg='yellow', bold=True)))
    print("  Twisted          : {0}".format(
        click.style(tx_ver, fg='yellow', bold=True)))
    print("  Python           : {0}/{1}".format(
        click.style(py_ver, fg='yellow', bold=True),
        click.style(py_ver_detail, fg='yellow', bold=True)))
    print("OS                 : {0}".format(
        click.style(platform.platform(), fg='yellow', bold=True)))
    print("Machine            : {0}".format(
        click.style(platform.machine(), fg='yellow', bold=True)))
    print("")
Пример #10
0
def run():
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform

    # create the top-level parser
    #
    import argparse
    parser = argparse.ArgumentParser()

    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='Debug on (optional).')

    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection (optional).')

    parser.add_argument('-c',
                        '--cbdir',
                        type=str,
                        help="Crossbar.io node directory (required).")

    parser.add_argument('-n',
                        '--node',
                        type=str,
                        help='Crossbar.io node ID (required).')

    parser.add_argument('-w',
                        '--worker',
                        type=str,
                        help='Crossbar.io worker ID (required).')

    parser.add_argument('-r',
                        '--realm',
                        type=str,
                        help='Crossbar.io node (management) realm (required).')

    parser.add_argument('-t',
                        '--type',
                        choices=['router', 'container'],
                        help='Worker type (required).')

    parser.add_argument('--title',
                        type=str,
                        default=None,
                        help='Worker process title to set (optional).')

    options = parser.parse_args()

    # make sure logging to something else than stdio is setup _first_
    #
    from twisted.python import log
    from crossbar.twisted.processutil import BareFormatFileLogObserver
    flo = BareFormatFileLogObserver(sys.stderr)
    log.startLoggingWithObserver(flo.emit)

    try:
        import setproctitle
    except ImportError:
        log.msg("Warning: could not set worker process title (setproctitle not installed)")
    else:
        # set process title if requested to
        #
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            WORKER_TYPE_TO_TITLE = {
                'router': 'crossbar-worker [router]',
                'container': 'crossbar-worker [container]'
            }
            setproctitle.setproctitle(WORKER_TYPE_TO_TITLE[options.type].strip())

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    from twisted.python.reflect import qual
    log.msg("Running under {} using {} reactor".format(platform.python_implementation(), qual(reactor.__class__).split('.')[-1]))

    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    from crossbar.worker.router import RouterWorkerSession
    from crossbar.worker.container import ContainerWorkerSession

    WORKER_TYPE_TO_CLASS = {
        'router': RouterWorkerSession,
        'container': ContainerWorkerSession
    }

    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):

        def connectionLost(self, reason):
            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                log.msg("Connection to node controller lost.")
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                pass
            finally:
                # loosing the connection to the node controller is fatal:
                # stop the reactor and exit with error
                if reactor.running:
                    reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
                    reactor.stop()
                else:
                    sys.exit(1)

    try:
        # create a WAMP application session factory
        #
        from autobahn.twisted.wamp import ApplicationSessionFactory
        from autobahn.wamp.types import ComponentConfig

        session_config = ComponentConfig(realm=options.realm, extra=options)
        session_factory = ApplicationSessionFactory(session_config)
        session_factory.session = WORKER_TYPE_TO_CLASS[options.type]

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug=False, debug_wamp=False)
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        stdio.StandardIO(proto)

        # now start reactor loop
        #
        log.msg("Entering event loop ..")
        reactor.run()

    except Exception as e:
        log.msg("Unhandled exception: {}".format(e))
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #11
0
def run_command_start(options):
    """
   Subcommand "crossbar start".
   """
    ## do not allow to run more than one Crossbar.io instance
    ## from the same Crossbar.io node directory
    ##
    pid_data = check_is_running(options.cbdir)
    if pid_data:
        print(
            "Crossbar.io is already running from node directory {} (PID {}).".
            format(options.cbdir, pid_data['pid']))
        sys.exit(1)
    else:
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        with open(fp, 'w') as fd:
            argv = options.argv
            options_dump = vars(options)
            del options_dump['func']
            del options_dump['argv']
            pid_data = {
                'pid': os.getpid(),
                'argv': argv,
                'options': options_dump
            }
            fd.write("{}\n".format(
                json.dumps(pid_data,
                           sort_keys=False,
                           indent=3,
                           separators=(',', ': '))))

    ## we use an Autobahn utility to import the "best" available Twisted reactor
    ##
    reactor = install_reactor(options.reactor, options.debug)

    ## remove node PID file when reactor exits
    ##
    def remove_pid_file():
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        if os.path.isfile(fp):
            os.remove(fp)

    reactor.addSystemEventTrigger('after', 'shutdown', remove_pid_file)

    ## start Twisted logging
    ##
    if not options.logdir:
        logfd = sys.stderr
    else:
        from twisted.python.logfile import DailyLogFile
        logfd = DailyLogFile.fromFullPath(
            os.path.join(options.logdir, 'node.log'))

    from crossbar.twisted.processutil import DefaultSystemFileLogObserver
    flo = DefaultSystemFileLogObserver(logfd,
                                       system="{:<10} {:>6}".format(
                                           "Controller", os.getpid()))
    log.startLoggingWithObserver(flo.emit)

    log.msg("=" * 20 + " Crossbar.io " + "=" * 20 + "\n")

    import crossbar
    log.msg("Crossbar.io {} starting".format(crossbar.__version__))

    from twisted.python.reflect import qual
    log.msg("Running on {} using {} reactor".format(
        platform.python_implementation(),
        qual(reactor.__class__).split('.')[-1]))
    log.msg("Starting from node directory {}".format(options.cbdir))

    ## create and start Crossbar.io node
    ##
    from crossbar.controller.node import Node
    node = Node(reactor, options)
    node.start()

    try:
        log.msg("Entering reactor event loop ...")
        reactor.run()
    except Exception as e:
        log.msg("Could not start reactor: {0}".format(e))
Пример #12
0
def run():
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.

    def ignore(sig, frame):
        log.debug("Ignoring SIGINT in worker.")
    signal.signal(signal.SIGINT, ignore)

    # create the top-level parser
    #
    import argparse
    parser = argparse.ArgumentParser()

    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection (optional).')

    parser.add_argument('--loglevel',
                        default="info",
                        choices=['none', 'error', 'warn', 'info', 'debug', 'trace'],
                        help='Initial log level.')

    parser.add_argument('-c',
                        '--cbdir',
                        type=str,
                        help="Crossbar.io node directory (required).")

    parser.add_argument('-n',
                        '--node',
                        type=str,
                        help='Crossbar.io node ID (required).')

    parser.add_argument('-w',
                        '--worker',
                        type=str,
                        help='Crossbar.io worker ID (required).')

    parser.add_argument('-r',
                        '--realm',
                        type=str,
                        help='Crossbar.io node (management) realm (required).')

    parser.add_argument('-t',
                        '--type',
                        choices=['router', 'container'],
                        help='Worker type (required).')

    parser.add_argument('--title',
                        type=str,
                        default=None,
                        help='Worker process title to set (optional).')

    options = parser.parse_args()

    # make sure logging to something else than stdio is setup _first_
    #
    from crossbar._logging import make_JSON_observer, cb_logging_aware, _stderr
    from crossbar._logging import make_logger, log_publisher, start_logging
    from crossbar._logging import set_global_log_level

    # Set the global log level
    set_global_log_level(options.loglevel)

    log = make_logger()

    # Print a magic phrase that tells the capturing logger that it supports
    # Crossbar's rich logging
    print(cb_logging_aware, file=_stderr)
    _stderr.flush()

    flo = make_JSON_observer(_stderr)
    log_publisher.addObserver(flo)
    start_logging()

    try:
        import setproctitle
    except ImportError:
        log.debug("Could not set worker process title (setproctitle not installed)")
    else:
        # set process title if requested to
        #
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            WORKER_TYPE_TO_TITLE = {
                'router': 'crossbar-worker [router]',
                'container': 'crossbar-worker [container]'
            }
            setproctitle.setproctitle(WORKER_TYPE_TO_TITLE[options.type].strip())

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    from twisted.python.reflect import qual
    log.info("Worker running under {python}-{reactor}",
             python=platform.python_implementation(),
             reactor=qual(reactor.__class__).split('.')[-1])

    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    from crossbar.worker.router import RouterWorkerSession
    from crossbar.worker.container import ContainerWorkerSession

    WORKER_TYPE_TO_CLASS = {
        'router': RouterWorkerSession,
        'container': ContainerWorkerSession
    }

    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):

        def connectionLost(self, reason):
            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                log.warn("Connection to node controller lost.")
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                pass
            finally:
                # losing the connection to the node controller is fatal:
                # stop the reactor and exit with error
                log.info("No more controller connection; shutting down.")
                reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
                try:
                    reactor.stop()
                except ReactorNotRunning:
                    pass

    try:
        # create a WAMP application session factory
        #
        from autobahn.twisted.wamp import ApplicationSessionFactory
        from autobahn.wamp.types import ComponentConfig

        session_config = ComponentConfig(realm=options.realm, extra=options)
        session_factory = ApplicationSessionFactory(session_config)
        session_factory.session = WORKER_TYPE_TO_CLASS[options.type]

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug=False, debug_wamp=False)
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.python.runtime import platform as _platform
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        if _platform.isWindows():
            stdio.StandardIO(proto)
        else:
            stdio.StandardIO(proto, stdout=3)

        # now start reactor loop
        #
        if False:
            log.info("vmprof enabled.")

            import os
            import vmprof

            PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid())

            outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
            vmprof.enable(outfd, period=0.01)

            log.info("Entering event loop...")
            reactor.run()

            vmprof.disable()
        else:
            log.debug("Entering event loop...")
            reactor.run()

    except Exception as e:
        log.info("Unhandled exception: {}".format(e))
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #13
0
            except Exception:
                self.log.failure(None)

        else:
            self.log.error("Received NOTIFY on unknown channel {channel}",
                           channel=notify.channel)


if __name__ == '__main__':
    from autobahn.twisted.choosereactor import install_reactor
    from autobahn.twisted.wamp import ApplicationRunner

    import sys
    if sys.platform == 'win32':
        # IOCPReactor does did not implement addWriter: use select reactor
        install_reactor('select')
    else:
        install_reactor()

    config = {
        u'database': {
            u'host': u'127.0.0.1',
            u'port': 5432,
            u'port': u'$DBPORT',
            u'database': u'test',
            #         u'user': u'$DBUSER',
            u'user': u'testuser',
            u'password': u'$DBPASSWORD'
            #         u'password': u'testuser'
        }
    }
Пример #14
0
         except Exception as e:
            print e
      else:
         print "unknown channel"



if __name__ == '__main__':
   from autobahn.twisted.choosereactor import install_reactor
   from autobahn.twisted.wamp import ApplicationRunner

   import sys
   if sys.platform == 'win32':
      # IOCPReactor does did not implement addWriter: use select reactor
      install_reactor('select')
   else:
      install_reactor()

   config = {
      'database': {
         'host': u'127.0.0.1',
         'port': 5432,
         'port': u'$DBPORT',
         'database': u'test',
#         'user': u'$DBUSER',
         'user': u'testuser',
         'password': u'$DBPASSWORD'
#         'password': u'testuser'
      }
   }
Пример #15
0
def run(prog=None, args=None, reactor=None):
    """
    Entry point of Crossbar.io CLI.
    """

    loglevel_args = {
        "type": str,
        "default": 'info',
        "choices": ['none', 'error', 'warn', 'info', 'debug', 'trace'],
        "help": ("How much Crossbar.io should log to the terminal, in order "
                 "of verbosity.")
    }

    # create the top-level parser
    #
    parser = argparse.ArgumentParser(prog='crossbar',
                                     description="Crossbar.io - Polyglot application router - http://crossbar.io")

    # top-level options
    #
    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection')

    # create subcommand parser
    #
    subparsers = parser.add_subparsers(dest='command',
                                       title='commands',
                                       help='Crossbar.io command to run')
    subparsers.required = True

    # "version" command
    #
    parser_version = subparsers.add_parser('version',
                                           help='Print software versions.')

    parser_version.add_argument('--loglevel',
                                **loglevel_args)

    parser_version.set_defaults(func=run_command_version)

    # "init" command
    #
    parser_init = subparsers.add_parser('init',
                                        help='Initialize a new Crossbar.io node.')

    parser_init.set_defaults(func=run_command_init)

    parser_init.add_argument('--template',
                             type=str,
                             default='default',
                             help="Template for initialization")

    parser_init.add_argument('--appdir',
                             type=str,
                             default=None,
                             help="Application base directory where to create app and node from template.")

    # "templates" command
    #
    parser_templates = subparsers.add_parser('templates',
                                             help='List templates available for initializing a new Crossbar.io node.')

    parser_templates.set_defaults(func=run_command_templates)

    # "start" command
    #
    parser_start = subparsers.add_parser('start',
                                         help='Start a Crossbar.io node.')

    parser_start.set_defaults(func=run_command_start)

    parser_start.add_argument('--cbdir',
                              type=str,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_start.add_argument('--config',
                              type=str,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    parser_start.add_argument('--logdir',
                              type=str,
                              default=None,
                              help="Crossbar.io log directory (default: <Crossbar Node Directory>/)")

    parser_start.add_argument('--logtofile',
                              action='store_true',
                              help="Whether or not to log to file")

    parser_start.add_argument('--loglevel',
                              **loglevel_args)

    parser_start.add_argument('--logformat',
                              type=str,
                              default='colour',
                              choices=['syslogd', 'nocolour', 'colour'],
                              help="The format of the logs -- suitable for syslogd, not coloured, or coloured.")

    # "stop" command
    #
    parser_stop = subparsers.add_parser('stop',
                                        help='Stop a Crossbar.io node.')

    parser_stop.add_argument('--cbdir',
                             type=str,
                             default=None,
                             help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_stop.set_defaults(func=run_command_stop)

    # "restart" command
    #
    parser_restart = subparsers.add_parser('restart',
                                           help='Restart a Crossbar.io node.')

    parser_restart.add_argument('--cbdir',
                                type=str,
                                default=None,
                                help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_restart.set_defaults(func=run_command_restart)

    # "status" command
    #
    parser_status = subparsers.add_parser('status',
                                          help='Checks whether a Crossbar.io node is running.')

    parser_status.add_argument('--cbdir',
                               type=str,
                               default=None,
                               help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_status.set_defaults(func=run_command_status)

    # "check" command
    #
    parser_check = subparsers.add_parser('check',
                                         help='Check a Crossbar.io node`s local configuration file.')

    parser_check.set_defaults(func=run_command_check)

    parser_check.add_argument('--cbdir',
                              type=str,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=str,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "convert" command
    #
    parser_check = subparsers.add_parser('convert',
                                         help='Convert a Crossbar.io node`s local configuration file from JSON to YAML or vice versa.')

    parser_check.set_defaults(func=run_command_convert)

    parser_check.add_argument('--cbdir',
                              type=str,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=str,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # parse cmd line args
    #
    options = parser.parse_args(args)
    if args:
        options.argv = [prog] + args
    else:
        options.argv = sys.argv

    # Crossbar.io node directory
    #
    if hasattr(options, 'cbdir'):
        if not options.cbdir:
            if "CROSSBAR_DIR" in os.environ:
                options.cbdir = os.environ['CROSSBAR_DIR']
            else:
                options.cbdir = '.crossbar'
        options.cbdir = os.path.abspath(options.cbdir)

    # Crossbar.io node configuration file
    #
    if hasattr(options, 'config'):
        if not options.config:
            for f in ['config.json', 'config.yaml']:
                f = os.path.join(options.cbdir, f)
                if os.path.isfile(f) and os.access(f, os.R_OK):
                    options.config = f
                    break
            if not options.config:
                raise Exception("No config file specified, and neither CBDIR/config.json nor CBDIR/config.yaml exists")
        else:
            options.config = os.path.join(options.cbdir, options.config)

    # Log directory
    #
    if hasattr(options, 'logdir'):
        if options.logdir:
            options.logdir = os.path.abspath(os.path.join(options.cbdir, options.logdir))
            if not os.path.isdir(options.logdir):
                try:
                    os.mkdir(options.logdir)
                except Exception as e:
                    print("Could not create log directory: {}".format(e))
                    sys.exit(1)

    if not reactor:
        # try and get the log verboseness we want -- not all commands have a
        # loglevel, so just default to info in that case
        debug = getattr(options, "loglevel", "info") in ("debug", "trace")

        # we use an Autobahn utility to import the "best" available Twisted
        # reactor
        reactor = install_reactor(options.reactor, debug)

    # Start the logger
    _startlog(options, reactor)

    # run the subcommand selected
    #
    options.func(options, reactor=reactor)
Пример #16
0
def run(prog=None, args=None, reactor=None):
    """
    Entry point of Crossbar.io CLI.
    """

    loglevel_args = {
        "type": str,
        "default": 'info',
        "choices": ['none', 'error', 'warn', 'info', 'debug', 'trace'],
        "help": ("How much Crossbar.io should log to the terminal, in order "
                 "of verbosity.")
    }

    # create the top-level parser
    #
    parser = argparse.ArgumentParser(prog='crossbar',
                                     description="Crossbar.io - Polyglot application router - http://crossbar.io")

    # top-level options
    #
    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection')

    # create subcommand parser
    #
    subparsers = parser.add_subparsers(dest='command',
                                       title='commands',
                                       help='Crossbar.io command to run')
    subparsers.required = True

    # "version" command
    #
    parser_version = subparsers.add_parser('version',
                                           help='Print software versions.')

    parser_version.add_argument('--loglevel',
                                **loglevel_args)

    parser_version.set_defaults(func=run_command_version)

    # "init" command
    #
    parser_init = subparsers.add_parser('init',
                                        help='Initialize a new Crossbar.io node.')

    parser_init.set_defaults(func=run_command_init)

    parser_init.add_argument('--template',
                             type=str,
                             default='default',
                             help="Template for initialization")

    parser_init.add_argument('--appdir',
                             type=str,
                             default=None,
                             help="Application base directory where to create app and node from template.")

    # "templates" command
    #
    parser_templates = subparsers.add_parser('templates',
                                             help='List templates available for initializing a new Crossbar.io node.')

    parser_templates.set_defaults(func=run_command_templates)

    # "start" command
    #
    parser_start = subparsers.add_parser('start',
                                         help='Start a Crossbar.io node.')

    parser_start.set_defaults(func=run_command_start)

    parser_start.add_argument('--cbdir',
                              type=str,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_start.add_argument('--config',
                              type=str,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    parser_start.add_argument('--logdir',
                              type=str,
                              default=None,
                              help="Crossbar.io log directory (default: <Crossbar Node Directory>/)")

    parser_start.add_argument('--logtofile',
                              action='store_true',
                              help="Whether or not to log to file")

    parser_start.add_argument('--loglevel',
                              **loglevel_args)

    parser_start.add_argument('--logformat',
                              type=str,
                              default='colour',
                              choices=['syslogd', 'nocolour', 'colour'],
                              help="The format of the logs -- suitable for syslogd, not coloured, or coloured.")

    # "stop" command
    #
    parser_stop = subparsers.add_parser('stop',
                                        help='Stop a Crossbar.io node.')

    parser_stop.add_argument('--cbdir',
                             type=str,
                             default=None,
                             help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_stop.set_defaults(func=run_command_stop)

    # "restart" command
    #
    parser_restart = subparsers.add_parser('restart',
                                           help='Restart a Crossbar.io node.')

    parser_restart.add_argument('--cbdir',
                                type=str,
                                default=None,
                                help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_restart.set_defaults(func=run_command_restart)

    # "status" command
    #
    parser_status = subparsers.add_parser('status',
                                          help='Checks whether a Crossbar.io node is running.')

    parser_status.add_argument('--cbdir',
                               type=str,
                               default=None,
                               help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_status.set_defaults(func=run_command_status)

    # "check" command
    #
    parser_check = subparsers.add_parser('check',
                                         help='Check a Crossbar.io node`s local configuration file.')

    parser_check.set_defaults(func=run_command_check)

    parser_check.add_argument('--cbdir',
                              type=str,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=str,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "convert" command
    #
    parser_check = subparsers.add_parser('convert',
                                         help='Convert a Crossbar.io node`s local configuration file from JSON to YAML or vice versa.')

    parser_check.set_defaults(func=run_command_convert)

    parser_check.add_argument('--cbdir',
                              type=str,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=str,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # parse cmd line args
    #
    options = parser.parse_args(args)
    if args:
        options.argv = [prog] + args
    else:
        options.argv = sys.argv

    # Crossbar.io node directory
    #
    if hasattr(options, 'cbdir'):
        if not options.cbdir:
            if "CROSSBAR_DIR" in os.environ:
                options.cbdir = os.environ['CROSSBAR_DIR']
            else:
                options.cbdir = '.crossbar'
        options.cbdir = os.path.abspath(options.cbdir)

    # Crossbar.io node configuration file
    #
    if hasattr(options, 'config'):
        if not options.config:
            for f in ['config.json', 'config.yaml']:
                f = os.path.join(options.cbdir, f)
                if os.path.isfile(f) and os.access(f, os.R_OK):
                    options.config = f
                    break
            if not options.config:
                raise Exception("No config file specified, and neither CBDIR/config.json nor CBDIR/config.yaml exists")
        else:
            options.config = os.path.join(options.cbdir, options.config)

    # Log directory
    #
    if hasattr(options, 'logdir'):
        if options.logdir:
            options.logdir = os.path.abspath(os.path.join(options.cbdir, options.logdir))
            if not os.path.isdir(options.logdir):
                try:
                    os.mkdir(options.logdir)
                except Exception as e:
                    print("Could not create log directory: {}".format(e))
                    sys.exit(1)

    if not reactor:
        # try and get the log verboseness we want -- not all commands have a
        # loglevel, so just default to info in that case
        debug = getattr(options, "loglevel", "info") in ("debug", "trace")

        # we use an Autobahn utility to import the "best" available Twisted
        # reactor
        reactor = install_reactor(options.reactor, debug)

    # Start the logger
    _startlog(options, reactor)

    # run the subcommand selected
    #
    options.func(options, reactor=reactor)
Пример #17
0
def run():
   """
   Entry point into background worker process. This wires up stuff such that
   a WorkerProcess instance is talking WAMP over stdio to the node controller.
   """
   ## create the top-level parser
   ##
   import argparse
   parser = argparse.ArgumentParser()

   parser.add_argument('-d',
                       '--debug',
                       action = 'store_true',
                       help = 'Debug on.')

   parser.add_argument('--reactor',
                       default = None,
                       choices = ['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                       help = 'Explicit Twisted reactor selection')

   parser.add_argument('--cbdir',
                       type = str,
                       default = None,
                       help = "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

   parser.add_argument('-l',
                       '--logfile',
                       default = None,
                       help = 'Log to log file instead of stderr.')

   options = parser.parse_args()

   ## make sure logging to something else than stdio is setup _first_
   ##
   if options.logfile:
      log.startLogging(open(options.logfile, 'a'))
   else:
      log.startLogging(sys.stderr)


   pid = os.getpid()

   ## Crossbar.io node directory
   ##
   if hasattr(options, 'cbdir') and not options.cbdir:
      if os.environ.has_key("CROSSBAR_DIR"):
         options.cbdir = os.environ['CROSSBAR_DIR']
      else:
         options.cbdir = '.crossbar'

   options.cbdir = os.path.abspath(options.cbdir)


   ## we use an Autobahn utility to import the "best" available Twisted reactor
   ##
   from autobahn.twisted.choosereactor import install_reactor
   reactor = install_reactor(options.reactor)

   ##
   from twisted.python.reflect import qual
   log.msg("Worker {}: starting at node directory {} on {} ..".format(pid, options.cbdir, qual(reactor.__class__).split('.')[-1]))

   try:
      ## create a WAMP application session factory
      ##
      from autobahn.twisted.wamp import ApplicationSessionFactory
      session_factory = ApplicationSessionFactory()
      session_factory.options = options
      session_factory.session = WorkerProcess

      ## create a WAMP-over-WebSocket transport server factory
      ##
      from autobahn.twisted.websocket import WampWebSocketServerFactory
      transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug = False)
      transport_factory.setProtocolOptions(failByDrop = False)

      ## create a protocol instance and wire up to stdio
      ##
      from twisted.internet import stdio
      proto = transport_factory.buildProtocol(None)
      stdio.StandardIO(proto)

      ## now start reactor loop
      ##
      log.msg("Worker {}: entering event loop ..".format(pid))
      reactor.run()

   except Exception as e:
      log.msg("Worker {}: Unhandled exception - {}".format(pid, e))
      raise e
      sys.exit(1)
Пример #18
0
def run():
    import sys, argparse
    from twisted.python import log
    from twisted.internet.endpoints import serverFromString

    ## parse command line arguments
    ##

    def_wsocket = 'ws://127.0.0.1:8080/ws'
    def_xsocket = None
    def_user = '******'
    def_secret = '123test'
    def_realm = 'realm1'
    def_topic_base = 'sys'
    def_dsn = 'dbname=autobahn host=localhost user=autouser'
    def_endpoint = 'tcp:8080'
    def_engine = 'PG9_4'

    p = argparse.ArgumentParser(
        description="basicrouter example with database")

    p.add_argument('-w',
                   '--websocket',
                   action='store',
                   dest='wsocket',
                   default=def_wsocket,
                   help='web socket ' + def_wsocket)
    p.add_argument('-x',
                   '--xsocket',
                   action='store',
                   dest='xsocket',
                   default=def_xsocket,
                   help='x socket definition, default is: None ')
    p.add_argument('-r',
                   '--realm',
                   action='store',
                   dest='realm',
                   default=def_realm,
                   help='connect to websocket using "realm", default ' +
                   def_realm)
    p.add_argument('-v',
                   '--verbose',
                   action='store_true',
                   dest='verbose',
                   default=False,
                   help='Verbose logging for debugging')
    p.add_argument('-u',
                   '--user',
                   action='store',
                   dest='user',
                   default=def_user,
                   help='connect to websocket as user, default is: ' +
                   def_user)
    p.add_argument('-s',
                   '--secret',
                   action='store',
                   dest='password',
                   default=def_secret,
                   help='users "secret" password')
    p.add_argument('--debug',
                   action='store_true',
                   dest='debug',
                   default=False,
                   help='Autobahn layer debugging')
    p.add_argument(
        '-e',
        '--engine',
        action='store',
        dest='engine',
        default=def_engine,
        help=
        'if specified, a database engine will be attached. Note engine is rooted on --topic'
    )
    p.add_argument(
        "--endpoint",
        type=str,
        default="tcp:8080",
        help=
        'Twisted server endpoint descriptor, e.g. "tcp:8080" or "unix:/tmp/mywebsocket", default is "'
        + def_endpoint + '"')
    p.add_argument(
        '-d',
        '--dsn',
        action='store',
        dest='dsn',
        default=def_dsn,
        help='if specified the database in dsn will be connected and ready')
    p.add_argument(
        '-t',
        '--topic',
        action='store',
        dest='topic_base',
        default=def_topic_base,
        help=
        'if you specify --dsn then you will need a topic to root it on, the default '
        + def_topic_base + ' is fine.')

    args = p.parse_args()
    if args.verbose:
        log.startLogging(sys.stdout)

    ## we use an Autobahn utility to install the "best" available Twisted reactor
    ##
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor()
    log.msg("Running on reactor {}".format(reactor))

    # database workers...
    userdb = UserDb(topic_base=args.topic_base + '.db', debug=args.verbose)
    sessiondb = SessionDb(topic_base=args.topic_base, debug=args.verbose)

    ## create a WAMP router factory
    ##
    component_config = types.ComponentConfig(realm=args.realm)
    xomponent_config = types.ComponentConfig(realm=args.realm)
    ai = {
        'auth_type': 'wampcra',
        'auth_user': args.user,
        'auth_password': args.password
    }

    from autobahn.twisted.wamp import RouterFactory
    router_factory = RouterFactory()
    authorization_session = AuthorizeSession(component_config,
                                             topic_base=args.topic_base +
                                             '.db',
                                             debug=args.verbose,
                                             db=sessiondb,
                                             router=AuthorizeRouter)
    router_factory.router = authorization_session.ret_func

    ## create a WAMP router session factory
    ##
    from autobahn.twisted.wamp import RouterSessionFactory
    session_factory = RouterSessionFactory(router_factory)
    session_factory.session = MyRouterSession

    log.msg("session_factory.session")

    session_factory.userdb = userdb
    session_factory.sessiondb = sessiondb

    log.msg("userdb, sessiondb")

    sessiondb_component = SessionData(component_config,
                                      session_factory.sessiondb,
                                      topic_base=args.topic_base)
    session_factory.add(sessiondb_component)
    session_factory.add(authorization_session)

    log.msg("session_factory")

    db_session = DB(component_config,
                    engine=args.engine,
                    topic_base=args.topic_base + '.db',
                    dsn=args.dsn,
                    debug=args.verbose)
    session_factory.add(db_session)
    session_factory.userdb.set_session(db_session)
    session_factory.sessiondb.set_session(db_session)

    ## create a WAMP-over-WebSocket transport server factory
    ##
    from autobahn.twisted.websocket import WampWebSocketServerFactory
    transport_factory = WampWebSocketServerFactory(session_factory,
                                                   debug=args.debug)
    transport_factory.setProtocolOptions(failByDrop=False)

    ## start the server from an endpoint
    ##
    ## this address clash detection was a goody I got from stackoverflow:
    ## http://stackoverflow.com/questions/12007316/exiting-twisted-application-after-listenfailure
    server = serverFromString(reactor, args.endpoint)

    def listen():
        srv = server.listen(transport_factory)

        def ListenFailed(reason):
            log.msg("On Startup Listen Failed with {}".format(reason))
            reactor.stop()

        srv.addErrback(ListenFailed)

    def addsession():
        log.msg("here are three sessions {} {} {}".format(
            authorization_session, sessiondb_component, db_session))
        qv = {
            "sessiondb_component": sessiondb_component._session_id,
            "db_session": db_session._session_id,
            "authorization_session": authorization_session._session_id
        }
        session_factory.sessiondb.set_system_sessions(qv)
        session_factory.sessiondb.add(0, sessiondb_component._session_id,
                                      sessiondb_component)
        session_factory.sessiondb.add(0, db_session._session_id, db_session)
        session_factory.sessiondb.add(0, authorization_session._session_id,
                                      authorization_session)

    reactor.callWhenRunning(listen)
    reactor.callWhenRunning(addsession)

    # if we set this router to be mastered by another, then start communicating with it
    if args.xsocket is not None:
        xdb = Xomponent(config=xomponent_config,
                        authinfo=ai,
                        topic_base=args.topic_base,
                        debug=args.verbose,
                        command='session',
                        action='list',
                        action_args={})
        xdb.set_session(db_session)
        runner = ApplicationRunner(args.xsocket, args.realm)
        runner.run(lambda _: xdb, start_reactor=False)

    reactor.run()
Пример #19
0
def _run_command_exec_worker(options, reactor=None, personality=None):
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # https://coverage.readthedocs.io/en/coverage-4.4.2/subprocess.html#measuring-sub-processes
    MEASURING_COVERAGE = False
    if 'COVERAGE_PROCESS_START' in os.environ:
        try:
            import coverage
        except ImportError:
            pass
        else:
            # The following will read the environment variable COVERAGE_PROCESS_START,
            # and that should be set to the .coveragerc file:
            #
            #   export COVERAGE_PROCESS_START=${PWD}/.coveragerc
            #
            coverage.process_startup()
            MEASURING_COVERAGE = True

    # we use an Autobahn utility to import the "best" available Twisted reactor
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    # make sure logging to something else than stdio is setup _first_
    from crossbar._logging import make_JSON_observer, cb_logging_aware
    from txaio import make_logger, start_logging
    from twisted.logger import globalLogPublisher
    from twisted.python.reflect import qual

    log = make_logger()

    # Print a magic phrase that tells the capturing logger that it supports
    # Crossbar's rich logging
    print(cb_logging_aware, file=sys.__stderr__)
    sys.__stderr__.flush()

    flo = make_JSON_observer(sys.__stderr__)
    globalLogPublisher.addObserver(flo)

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.
    def ignore(sig, frame):
        log.debug("Ignoring SIGINT in worker.")
    signal.signal(signal.SIGINT, ignore)

    # actually begin logging
    start_logging(None, options.loglevel)

    # get personality klass, eg "crossbar.personality.Personality"
    l = options.personality.split('.')
    personality_module, personality_klass = '.'.join(l[:-1]), l[-1]

    # now load the personality module and class
    _mod = importlib.import_module(personality_module)
    Personality = getattr(_mod, personality_klass)

    # get worker klass, eg "crossbar.worker.container.ContainerController"
    l = options.klass.split('.')
    worker_module, worker_klass = '.'.join(l[:-1]), l[-1]

    # now load the worker module and class
    _mod = importlib.import_module(worker_module)
    klass = getattr(_mod, worker_klass)

    log.info(
        'Starting worker "{worker_id}" for node "{node_id}" with personality "{personality}" {worker_class}',
        worker_id=options.worker,
        node_id=options.node,
        personality=Personality.NAME,
        worker_class=hltype(klass),
    )
    log.info(
        'Running as PID {pid} on {python}-{reactor}',
        pid=os.getpid(),
        python=platform.python_implementation(),
        reactor=qual(reactor.__class__).split('.')[-1],
    )
    if MEASURING_COVERAGE:
        log.info(hl('Code coverage measurements enabled (coverage={coverage_version}).', color='green', bold=True),
                 coverage_version=coverage.__version__)

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug("Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle('crossbar-worker [{}]'.format(options.klass))

    # node directory
    #
    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug("Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle(
                'crossbar-worker [{}]'.format(options.klass)
            )

    from twisted.internet.error import ConnectionDone
    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):

        def connectionLost(self, reason):
            # the behavior here differs slightly whether we're shutting down orderly
            # or shutting down because of "issues"
            if isinstance(reason.value, ConnectionDone):
                was_clean = True
            else:
                was_clean = False

            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                if was_clean:
                    log.info("Connection to node controller closed cleanly")
                else:
                    log.warn("Connection to node controller lost: {reason}", reason=reason)

                # give the WAMP transport a change to do it's thing
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                # we're in the process of shutting down .. so ignore ..
                pass
            finally:
                # after the connection to the node controller is gone,
                # the worker is "orphane", and should exit

                # determine process exit code
                if was_clean:
                    exit_code = 0
                else:
                    exit_code = 1

                # exit the whole worker process when the reactor has stopped
                reactor.addSystemEventTrigger('after', 'shutdown', os._exit, exit_code)

                # stop the reactor
                try:
                    reactor.stop()
                except ReactorNotRunning:
                    pass

    try:
        # define a WAMP application session factory
        #
        from autobahn.wamp.types import ComponentConfig

        def make_session():
            session_config = ComponentConfig(realm=options.realm, extra=options)
            session = klass(config=session_config, reactor=reactor, personality=Personality)
            return session

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(make_session, u'ws://localhost')
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.python.runtime import platform as _platform
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        if _platform.isWindows():
            stdio.StandardIO(proto)
        else:
            stdio.StandardIO(proto, stdout=3)

        # now start reactor loop
        #
        if False:
            log.info("vmprof enabled.")

            import os
            import vmprof

            PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid())

            outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
            vmprof.enable(outfd, period=0.01)

            log.info(hl('Entering event reactor ...', color='cyan', bold=True))
            reactor.run()

            vmprof.disable()
        else:
            log.info(hl('Entering event reactor ...', color='cyan', bold=True))
            reactor.run()

    except Exception as e:
        log.info("Unhandled exception: {e}", e=e)
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #20
0
def run(options, reactor=None):
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # make sure logging to something else than stdio is setup _first_
    #
    from crossbar._logging import make_JSON_observer, cb_logging_aware
    from txaio import make_logger, start_logging
    from twisted.logger import globalLogPublisher
    from twisted.python.reflect import qual

    log = make_logger()

    # Print a magic phrase that tells the capturing logger that it supports
    # Crossbar's rich logging
    print(cb_logging_aware, file=sys.__stderr__)
    sys.__stderr__.flush()

    flo = make_JSON_observer(sys.__stderr__)
    globalLogPublisher.addObserver(flo)

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.

    def ignore(sig, frame):
        log.debug("Ignoring SIGINT in worker.")

    signal.signal(signal.SIGINT, ignore)

    # actually begin logging
    start_logging(None, options.loglevel)

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    # eg: crossbar.worker.container.ContainerWorkerSession
    l = options.klass.split('.')
    worker_module, worker_klass = '.'.join(l[:-1]), l[-1]

    # now load the worker module and class
    _mod = importlib.import_module(worker_module)
    klass = getattr(_mod, worker_klass)

    log.info(
        'Started {worker_title} worker "{worker_id}" on node "{node_id}" [{klass} / {python}-{reactor}]',
        worker_title=klass.WORKER_TITLE,
        klass=options.klass,
        node_id=options.node,
        worker_id=options.worker,
        pid=os.getpid(),
        python=platform.python_implementation(),
        reactor=qual(reactor.__class__).split('.')[-1],
    )

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug(
            "Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle('crossbar-worker [{}]'.format(
                options.klass))

    # node directory
    #
    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug(
            "Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle('crossbar-worker [{}]'.format(
                options.klass))

    from twisted.internet.error import ConnectionDone
    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):
        def connectionLost(self, reason):
            # the behavior here differs slightly whether we're shutting down orderly
            # or shutting down because of "issues"
            if isinstance(reason.value, ConnectionDone):
                was_clean = True
            else:
                was_clean = False

            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                if was_clean:
                    log.info("Connection to node controller closed cleanly")
                else:
                    log.warn("Connection to node controller lost: {reason}",
                             reason=reason)

                # give the WAMP transport a change to do it's thing
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                # we're in the process of shutting down .. so ignore ..
                pass
            finally:
                # after the connection to the node controller is gone,
                # the worker is "orphane", and should exit

                # determine process exit code
                if was_clean:
                    exit_code = 0
                else:
                    exit_code = 1

                # exit the whole worker process when the reactor has stopped
                reactor.addSystemEventTrigger('after', 'shutdown', os._exit,
                                              exit_code)

                # stop the reactor
                try:
                    reactor.stop()
                except ReactorNotRunning:
                    pass

    try:
        # create a WAMP application session factory
        #
        from autobahn.twisted.wamp import ApplicationSessionFactory
        from autobahn.wamp.types import ComponentConfig

        session_config = ComponentConfig(realm=options.realm, extra=options)
        session_factory = ApplicationSessionFactory(session_config)
        session_factory.session = klass

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(session_factory,
                                                       u'ws://localhost')
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.python.runtime import platform as _platform
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        if _platform.isWindows():
            stdio.StandardIO(proto)
        else:
            stdio.StandardIO(proto, stdout=3)

        # now start reactor loop
        #
        if False:
            log.info("vmprof enabled.")

            import os
            import vmprof

            PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid())

            outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
            vmprof.enable(outfd, period=0.01)

            log.info("Entering event loop...")
            reactor.run()

            vmprof.disable()
        else:
            log.debug("Entering event loop...")
            reactor.run()

    except Exception as e:
        log.info("Unhandled exception: {e}", e=e)
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #21
0
def run():
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.

    def ignore(sig, frame):
        log.debug("Ignoring SIGINT in worker.")

    signal.signal(signal.SIGINT, ignore)

    # create the top-level parser
    #
    import argparse
    parser = argparse.ArgumentParser()

    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection (optional).')

    parser.add_argument(
        '--loglevel',
        default="info",
        choices=['none', 'error', 'warn', 'info', 'debug', 'trace'],
        help='Initial log level.')

    parser.add_argument('-c',
                        '--cbdir',
                        type=six.text_type,
                        help="Crossbar.io node directory (required).")

    parser.add_argument('-r',
                        '--realm',
                        type=six.text_type,
                        help='Crossbar.io node (management) realm (required).')

    parser.add_argument('-t',
                        '--type',
                        choices=['router', 'container', 'websocket-testee'],
                        help='Worker type (required).')

    parser.add_argument('-w',
                        '--worker',
                        type=six.text_type,
                        help='Crossbar.io worker ID (required).')

    parser.add_argument('--title',
                        type=six.text_type,
                        default=None,
                        help='Worker process title to set (optional).')

    parser.add_argument(
        '--expose_controller',
        type=bool,
        default=False,
        help=
        'Expose node controller session to all components (this feature requires Crossbar.io Fabric extension).'
    )

    parser.add_argument(
        '--expose_shared',
        type=bool,
        default=False,
        help=
        'Expose a shared object to all components (this feature requires Crossbar.io Fabric extension).'
    )

    options = parser.parse_args()

    # make sure logging to something else than stdio is setup _first_
    #
    from crossbar._logging import make_JSON_observer, cb_logging_aware
    from txaio import make_logger, start_logging
    from twisted.logger import globalLogPublisher

    log = make_logger()

    # Print a magic phrase that tells the capturing logger that it supports
    # Crossbar's rich logging
    print(cb_logging_aware, file=sys.__stderr__)
    sys.__stderr__.flush()

    flo = make_JSON_observer(sys.__stderr__)
    globalLogPublisher.addObserver(flo)
    start_logging(None, options.loglevel)

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    WORKER_TYPE_TO_TITLE = {
        'router': 'Router',
        'container': 'Container',
        'websocket-testee': 'WebSocket Testee'
    }

    from twisted.python.reflect import qual
    log.info(
        '{worker_title} worker "{worker_id}" process {pid} starting on {python}-{reactor} ..',
        worker_title=WORKER_TYPE_TO_TITLE[options.type],
        worker_id=options.worker,
        pid=os.getpid(),
        python=platform.python_implementation(),
        reactor=qual(reactor.__class__).split('.')[-1])

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug(
            "Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            WORKER_TYPE_TO_PROCESS_TITLE = {
                'router': 'crossbar-worker [router]',
                'container': 'crossbar-worker [container]',
                'websocket-testee': 'crossbar-worker [websocket-testee]'
            }
            setproctitle.setproctitle(
                WORKER_TYPE_TO_PROCESS_TITLE[options.type].strip())

    # node directory
    #
    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    from crossbar.worker.router import RouterWorkerSession
    from crossbar.worker.container import ContainerWorkerSession
    from crossbar.worker.testee import WebSocketTesteeWorkerSession

    WORKER_TYPE_TO_CLASS = {
        'router': RouterWorkerSession,
        'container': ContainerWorkerSession,
        'websocket-testee': WebSocketTesteeWorkerSession
    }

    from twisted.internet.error import ConnectionDone
    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):
        def connectionLost(self, reason):
            # the behavior here differs slightly whether we're shutting down orderly
            # or shutting down because of "issues"
            if isinstance(reason.value, ConnectionDone):
                was_clean = True
            else:
                was_clean = False

            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                if was_clean:
                    log.info("Connection to node controller closed cleanly")
                else:
                    log.warn("Connection to node controller lost: {reason}",
                             reason=reason)

                # give the WAMP transport a change to do it's thing
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                # we're in the process of shutting down .. so ignore ..
                pass
            finally:
                # after the connection to the node controller is gone,
                # the worker is "orphane", and should exit

                # determine process exit code
                if was_clean:
                    exit_code = 0
                else:
                    exit_code = 1

                # exit the whole worker process when the reactor has stopped
                reactor.addSystemEventTrigger('after', 'shutdown', os._exit,
                                              exit_code)

                # stop the reactor
                try:
                    reactor.stop()
                except ReactorNotRunning:
                    pass

    try:
        # create a WAMP application session factory
        #
        from autobahn.twisted.wamp import ApplicationSessionFactory
        from autobahn.wamp.types import ComponentConfig

        session_config = ComponentConfig(realm=options.realm, extra=options)
        session_factory = ApplicationSessionFactory(session_config)
        session_factory.session = WORKER_TYPE_TO_CLASS[options.type]

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(session_factory,
                                                       u'ws://localhost')
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.python.runtime import platform as _platform
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        if _platform.isWindows():
            stdio.StandardIO(proto)
        else:
            stdio.StandardIO(proto, stdout=3)

        # now start reactor loop
        #
        if False:
            log.info("vmprof enabled.")

            import os
            import vmprof

            PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid())

            outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
            vmprof.enable(outfd, period=0.01)

            log.info("Entering event loop...")
            reactor.run()

            vmprof.disable()
        else:
            log.debug("Entering event loop...")
            reactor.run()

    except Exception as e:
        log.info("Unhandled exception: {e}", e=e)
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #22
0
from autobahn.twisted.choosereactor import install_reactor

install_reactor(verbose=True)

import sys

from twisted.internet import protocol, reactor, endpoints
from twisted.python import log

from twisted.internet.defer import inlineCallbacks, DeferredList
from twisted.internet.task import LoopingCall

from autobahn.util import rtime

from autobahn.twisted.util import sleep

from collections import deque

log.startLogging(sys.stdout)

import psutil
p = psutil.Process()
p.cpu_affinity([1])
print("CPU affinity set: {}".format(p.cpu_affinity()))

size_histo = {}


def print_histo():
    print size_histo
Пример #23
0
def run():
    import sys, argparse
    from twisted.python import log
    from twisted.internet.endpoints import serverFromString

    ## parse command line arguments
    ##

    def_wsocket = 'ws://127.0.0.1:8080/ws'
    def_realm = 'realm1'
    def_topic_base = 'sys'
    def_dsn = 'dbname=autobahn host=localhost user=autouser'
    def_endpoint='tcp:8080'
    def_engine = 'PG9_4'

    p = argparse.ArgumentParser(description="basicrouter example with database")

    p.add_argument('-w', '--websocket', action='store', dest='wsocket', default=def_wsocket,
                        help='web socket '+def_wsocket)
    p.add_argument('-r', '--realm', action='store', dest='realm', default=def_realm,
                        help='connect to websocket using "realm", default '+def_realm)
    p.add_argument('-v', '--verbose', action='store_true', dest='verbose',
            default=False, help='Verbose logging for debugging')
    p.add_argument('--debug', action='store_true', dest='debug',
            default=False, help='Autobahn layer debugging')
    p.add_argument('-e', '--engine', action='store', dest='engine', default=def_engine,
                        help='if specified, a database engine will be attached. Note engine is rooted on --topic')
    p.add_argument("--endpoint", type = str, default = "tcp:8080",
          help = 'Twisted server endpoint descriptor, e.g. "tcp:8080" or "unix:/tmp/mywebsocket", default is "' + def_endpoint + '"')
    p.add_argument('-d', '--dsn', action='store', dest='dsn', default=def_dsn,
                        help='if specified the database in dsn will be connected and ready')
    p.add_argument('-t', '--topic', action='store', dest='topic_base', default=def_topic_base,
                        help='if you specify --dsn then you will need a topic to root it on, the default ' + def_topic_base + ' is fine.')

    args = p.parse_args()
    if args.verbose:
        log.startLogging(sys.stdout)

    ## we use an Autobahn utility to install the "best" available Twisted reactor
    ##
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor()
    log.msg("Running on reactor {}".format(reactor))

    # database workers...
    userdb = UserDb(topic_base=args.topic_base+'.db',debug=args.verbose)
    sessiondb = SessionDb(topic_base=args.topic_base,debug=args.verbose)

    ## create a WAMP router factory
    ##
    component_config = types.ComponentConfig(realm = args.realm)

    from autobahn.twisted.wamp import RouterFactory
    router_factory = RouterFactory()
    authorization_session = AuthorizeSession(component_config,
        topic_base=args.topic_base+'.db',debug=args.verbose,db=sessiondb,router=AuthorizeRouter)
    router_factory.router = authorization_session.ret_func

    ## create a WAMP router session factory
    ##
    from autobahn.twisted.wamp import RouterSessionFactory
    session_factory = RouterSessionFactory(router_factory)
    session_factory.session = MyRouterSession

    log.msg("session_factory.session")

    session_factory.userdb = userdb
    session_factory.sessiondb = sessiondb

    log.msg("userdb, sessiondb")

    sessiondb_component = SessionData(component_config,session_factory.sessiondb,
        topic_base=args.topic_base)
    session_factory.add(sessiondb_component)
    session_factory.add(authorization_session)

    log.msg("session_factory")

    db_session = DB(component_config, engine=args.engine,
        topic_base=args.topic_base+'.db', dsn=args.dsn, debug=args.verbose)
    session_factory.add(db_session)
    session_factory.userdb.set_session(db_session)
    session_factory.sessiondb.set_session(db_session)

    ## create a WAMP-over-WebSocket transport server factory
    ##
    from autobahn.twisted.websocket import WampWebSocketServerFactory
    transport_factory = WampWebSocketServerFactory(session_factory, debug = args.debug)
    transport_factory.setProtocolOptions(failByDrop = False)


    ## start the server from an endpoint
    ##
    ## this address clash detection was a goody I got from stackoverflow:
    ## http://stackoverflow.com/questions/12007316/exiting-twisted-application-after-listenfailure
    server = serverFromString(reactor, args.endpoint)
    def listen():
        srv = server.listen(transport_factory)
        def ListenFailed(reason):
            log.msg("On Startup Listen Failed with {}".format(reason))
            reactor.stop()
        srv.addErrback(ListenFailed)

    def addsession():
        log.msg("here are three sessions {} {} {}".format(authorization_session, sessiondb_component, db_session))
        qv = {
            "sessiondb_component":sessiondb_component._session_id,
            "db_session":db_session._session_id,
            "authorization_session":authorization_session._session_id
        }
        session_factory.sessiondb.set_system_sessions(qv)
        session_factory.sessiondb.add(0, sessiondb_component._session_id, sessiondb_component)
        session_factory.sessiondb.add(0, db_session._session_id, db_session)
        session_factory.sessiondb.add(0, authorization_session._session_id, authorization_session)

    reactor.callWhenRunning(listen)
    reactor.callWhenRunning(addsession)
    reactor.run()
Пример #24
0
def run():
   """
   Entry point into background worker process. This wires up stuff such that
   a WorkerProcess instance is talking WAMP over stdio to the node controller.
   """
   ## create the top-level parser
   ##
   import argparse
   parser = argparse.ArgumentParser()

   parser.add_argument('-d',
                       '--debug',
                       action = 'store_true',
                       help = 'Debug on.')

   parser.add_argument('--reactor',
                       default = None,
                       choices = ['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                       help = 'Explicit Twisted reactor selection')

   parser.add_argument('--cbdir',
                       type = str,
                       default = None,
                       help = "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

   parser.add_argument('-n',
                       '--name',
                       default = None,
                       help = 'Optional process name to set.')

   options = parser.parse_args()


   ## make sure logging to something else than stdio is setup _first_
   ##
   from crossbar.twisted.process import BareFormatFileLogObserver
   flo = BareFormatFileLogObserver(sys.stderr)
   log.startLoggingWithObserver(flo.emit)


   ## the worker's PID
   ##
   pid = os.getpid()


   try:
      import setproctitle
   except ImportError:
      log.msg("Warning, could not set process title (setproctitle not installed)")
   else:
      ## set process title if requested to
      ##
      if options.name:
         setproctitle.setproctitle(options.name)
      else:
         setproctitle.setproctitle("Crossbar.io Worker")


   ## Crossbar.io node directory
   ##
   if hasattr(options, 'cbdir') and not options.cbdir:
      if os.environ.has_key("CROSSBAR_DIR"):
         options.cbdir = os.environ['CROSSBAR_DIR']
      else:
         options.cbdir = '.crossbar'

   options.cbdir = os.path.abspath(options.cbdir)
   log.msg("Starting from node directory {}.".format(options.cbdir))


   ## we use an Autobahn utility to import the "best" available Twisted reactor
   ##
   from autobahn.twisted.choosereactor import install_reactor
   reactor = install_reactor(options.reactor)

   from twisted.python.reflect import qual
   log.msg("Running on {} reactor.".format(qual(reactor.__class__).split('.')[-1]))


   from autobahn.twisted.websocket import WampWebSocketServerProtocol

   class WorkerServerProtocol(WampWebSocketServerProtocol):

      def connectionLost(self, reason):
         try:
            log.msg("Connection to node controller lost.")
            WampWebSocketServerProtocol.connectionLost(self, reason)
         except:
            pass
         finally:
            ## loosing the connection to the node controller (the pipes) is fatal.
            ## stop the reactor and exit with error
            if reactor.running:
               reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
               reactor.stop()
            else:
               sys.exit(1)

   try:
      ## create a WAMP application session factory
      ##
      from autobahn.twisted.wamp import ApplicationSessionFactory
      session_factory = ApplicationSessionFactory()
      session_factory.options = options
      session_factory.session = WorkerProcess

      ## create a WAMP-over-WebSocket transport server factory
      ##
      from autobahn.twisted.websocket import WampWebSocketServerFactory
      transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug = False)
      transport_factory.protocol = WorkerServerProtocol
      transport_factory.setProtocolOptions(failByDrop = False)

      ## create a protocol instance and wire up to stdio
      ##
      from twisted.internet import stdio
      proto = transport_factory.buildProtocol(None)
      stdio.StandardIO(proto)

      ## now start reactor loop
      ##
      log.msg("Entering event loop ..")

      #reactor.callLater(4, reactor.stop)
      reactor.run()

   except Exception as e:
      log.msg("Unhandled exception - {}".format(e))
      if reactor.running:
         reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
         reactor.stop()
      else:
         sys.exit(1)
Пример #25
0
               raise Exception("notification payload type 'table' not implemented")
            else:
               raise Exception("logic error")

         except Exception as e:
            print e
      else:
         print "unknown channel"



if __name__ == '__main__':
   from autobahn.twisted.choosereactor import install_reactor
   from autobahn.twisted.wamp import ApplicationRunner

   install_reactor()

   config = {
      'database': {
         'host': '127.0.0.1',
         'port': 5432,
         'database': 'test',
         'user': '******',
         'password': '******'      
      }
   }

   runner = ApplicationRunner(url = "ws://127.0.0.1:8080/ws",
      realm = "realm1", extra = config)
   runner.run(PostgreSQLDatabasePublisher)
Пример #26
0
def run():
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.

    def ignore(sig, frame):
        log.msg("Ignoring SIGINT in worker.")

    signal.signal(signal.SIGINT, ignore)

    # create the top-level parser
    #
    import argparse
    parser = argparse.ArgumentParser()

    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='Debug on (optional).')

    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection (optional).')

    parser.add_argument('-c',
                        '--cbdir',
                        type=str,
                        help="Crossbar.io node directory (required).")

    parser.add_argument('-n',
                        '--node',
                        type=str,
                        help='Crossbar.io node ID (required).')

    parser.add_argument('-w',
                        '--worker',
                        type=str,
                        help='Crossbar.io worker ID (required).')

    parser.add_argument('-r',
                        '--realm',
                        type=str,
                        help='Crossbar.io node (management) realm (required).')

    parser.add_argument('-t',
                        '--type',
                        choices=['router', 'container'],
                        help='Worker type (required).')

    parser.add_argument('--title',
                        type=str,
                        default=None,
                        help='Worker process title to set (optional).')

    options = parser.parse_args()

    # make sure logging to something else than stdio is setup _first_
    #
    from twisted.python import log
    from crossbar.twisted.processutil import BareFormatFileLogObserver
    flo = BareFormatFileLogObserver(sys.stderr)
    log.startLoggingWithObserver(flo.emit)

    try:
        import setproctitle
    except ImportError:
        log.msg(
            "Warning: could not set worker process title (setproctitle not installed)"
        )
    else:
        # set process title if requested to
        #
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            WORKER_TYPE_TO_TITLE = {
                'router': 'crossbar-worker [router]',
                'container': 'crossbar-worker [container]'
            }
            setproctitle.setproctitle(
                WORKER_TYPE_TO_TITLE[options.type].strip())

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    from twisted.python.reflect import qual
    log.msg("Running under {} using {} reactor".format(
        platform.python_implementation(),
        qual(reactor.__class__).split('.')[-1]))

    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    from crossbar.worker.router import RouterWorkerSession
    from crossbar.worker.container import ContainerWorkerSession

    WORKER_TYPE_TO_CLASS = {
        'router': RouterWorkerSession,
        'container': ContainerWorkerSession
    }

    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):
        def connectionLost(self, reason):
            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                log.msg("Connection to node controller lost.")
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                pass
            finally:
                # loosing the connection to the node controller is fatal:
                # stop the reactor and exit with error
                if reactor.running:
                    reactor.addSystemEventTrigger('after', 'shutdown',
                                                  os._exit, 1)
                    reactor.stop()
                # if the reactor *isn't* running, we're already shutting down

    try:
        # create a WAMP application session factory
        #
        from autobahn.twisted.wamp import ApplicationSessionFactory
        from autobahn.wamp.types import ComponentConfig

        session_config = ComponentConfig(realm=options.realm, extra=options)
        session_factory = ApplicationSessionFactory(session_config)
        session_factory.session = WORKER_TYPE_TO_CLASS[options.type]

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(session_factory,
                                                       "ws://localhost",
                                                       debug=False,
                                                       debug_wamp=False)
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        stdio.StandardIO(proto)

        # now start reactor loop
        #
        log.msg("Entering event loop ..")
        reactor.run()

    except Exception as e:
        log.msg("Unhandled exception: {}".format(e))
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #27
0
from autobahn.twisted.choosereactor import install_reactor

install_reactor(verbose=True)

import sys

from twisted.internet import protocol, reactor, endpoints
from twisted.python import log
from twisted.internet.task import LoopingCall

log.startLogging(sys.stdout)

import psutil
p = psutil.Process()
p.cpu_affinity([0])
print("CPU affinity set: {}".format(p.cpu_affinity()))

size_histo = {}
def print_histo():
    print size_histo

lc = LoopingCall(print_histo)
lc.start(1)


class Echo(protocol.Protocol):
    def dataReceived(self, data):
        l = len(data)
        if l not in size_histo:
            size_histo[l] = 0
Пример #28
0
##  You may obtain a copy of the License at
##
##      http://www.apache.org/licenses/LICENSE-2.0
##
##  Unless required by applicable law or agreed to in writing, software
##  distributed under the License is distributed on an "AS IS" BASIS,
##  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
##  See the License for the specific language governing permissions and
##  limitations under the License.
##
###############################################################################

import sys, argparse

from autobahn.twisted.choosereactor import install_reactor
install_reactor()

from twisted.python import log
from twisted.internet import reactor

import autobahn
from autobahn.twisted.websocket import listenWS

from autobahn.wamp1.protocol import WampServerFactory, \
                                    WampServerProtocol, \
                                    WampCraServerProtocol



class LoadLatencyBrokerProtocol(WampCraServerProtocol):
Пример #29
0
def _run_command_exec_worker(options, reactor=None, personality=None):
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # https://coverage.readthedocs.io/en/coverage-4.4.2/subprocess.html#measuring-sub-processes
    MEASURING_COVERAGE = False
    if 'COVERAGE_PROCESS_START' in os.environ:
        try:
            import coverage
        except ImportError:
            pass
        else:
            # The following will read the environment variable COVERAGE_PROCESS_START,
            # and that should be set to the .coveragerc file:
            #
            #   export COVERAGE_PROCESS_START=${PWD}/.coveragerc
            #
            coverage.process_startup()
            MEASURING_COVERAGE = True

    # we use an Autobahn utility to import the "best" available Twisted reactor
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    # make sure logging to something else than stdio is setup _first_
    from crossbar._logging import make_JSON_observer, cb_logging_aware
    from txaio import make_logger, start_logging
    from twisted.logger import globalLogPublisher
    from twisted.python.reflect import qual

    log = make_logger()

    # Print a magic phrase that tells the capturing logger that it supports
    # Crossbar's rich logging
    print(cb_logging_aware, file=sys.__stderr__)
    sys.__stderr__.flush()

    flo = make_JSON_observer(sys.__stderr__)
    globalLogPublisher.addObserver(flo)

    term_print('CROSSBAR[{}]:WORKER_STARTING'.format(options.worker))

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.
    def ignore(sig, frame):
        log.debug("Ignoring SIGINT in worker.")

    signal.signal(signal.SIGINT, ignore)

    # actually begin logging
    start_logging(None, options.loglevel)

    # get personality klass, eg "crossbar.personality.Personality"
    l = options.personality.split('.')
    personality_module, personality_klass = '.'.join(l[:-1]), l[-1]

    # now load the personality module and class
    _mod = importlib.import_module(personality_module)
    Personality = getattr(_mod, personality_klass)

    # get worker klass, eg "crossbar.worker.container.ContainerController"
    l = options.klass.split('.')
    worker_module, worker_klass = '.'.join(l[:-1]), l[-1]

    # now load the worker module and class
    _mod = importlib.import_module(worker_module)
    klass = getattr(_mod, worker_klass)

    log.info(
        'Starting {worker_type}-worker "{worker_id}" on node "{node_id}" (personality "{personality}") and local node management realm "{realm}" .. {worker_class}',
        worker_type=hl(klass.WORKER_TYPE),
        worker_id=hlid(options.worker),
        node_id=hlid(options.node),
        realm=hlid(options.realm),
        personality=hl(Personality.NAME),
        worker_class=hltype(klass),
    )
    log.info(
        'Running as PID {pid} on {python}-{reactor}',
        pid=os.getpid(),
        python=platform.python_implementation(),
        reactor=qual(reactor.__class__).split('.')[-1],
    )
    if MEASURING_COVERAGE:
        log.info(hl(
            'Code coverage measurements enabled (coverage={coverage_version}).',
            color='green',
            bold=True),
                 coverage_version=coverage.__version__)

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug(
            "Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle('crossbar-worker [{}]'.format(
                options.klass))

    # node directory
    #
    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug(
            "Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle('crossbar-worker [{}]'.format(
                options.klass))

    from twisted.internet.error import ConnectionDone
    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):
        def connectionLost(self, reason):
            # the behavior here differs slightly whether we're shutting down orderly
            # or shutting down because of "issues"
            if isinstance(reason.value, ConnectionDone):
                was_clean = True
            else:
                was_clean = False

            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                if was_clean:
                    log.info("Connection to node controller closed cleanly")
                else:
                    log.warn("Connection to node controller lost: {reason}",
                             reason=reason)

                # give the WAMP transport a change to do it's thing
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                # we're in the process of shutting down .. so ignore ..
                pass
            finally:
                # after the connection to the node controller is gone,
                # the worker is "orphane", and should exit

                # determine process exit code
                if was_clean:
                    exit_code = 0
                else:
                    exit_code = 1

                # exit the whole worker process when the reactor has stopped
                reactor.addSystemEventTrigger('after', 'shutdown', os._exit,
                                              exit_code)

                # stop the reactor
                try:
                    reactor.stop()
                except ReactorNotRunning:
                    pass

    # if vmprof global profiling is enabled via command line option, this will carry
    # the file where vmprof writes its profile data
    if _HAS_VMPROF:
        _vm_prof = {
            # need to put this into a dict, since FDs are ints, and python closures can't
            # write to this otherwise
            'outfd': None
        }

    # https://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IReactorCore.html
    # Each "system event" in Twisted, such as 'startup', 'shutdown', and 'persist', has 3 phases:
    # 'before', 'during', and 'after' (in that order, of course). These events will be fired
    # internally by the Reactor.

    def before_reactor_started():
        term_print('CROSSBAR[{}]:REACTOR_STARTING'.format(options.worker))

    def after_reactor_started():
        term_print('CROSSBAR[{}]:REACTOR_STARTED'.format(options.worker))

        if _HAS_VMPROF and options.vmprof:
            outfn = os.path.join(
                options.cbdir,
                '.vmprof-worker-{}-{}.dat'.format(options.worker, os.getpid()))
            _vm_prof['outfd'] = os.open(outfn,
                                        os.O_RDWR | os.O_CREAT | os.O_TRUNC)
            vmprof.enable(_vm_prof['outfd'], period=0.01)
            term_print('CROSSBAR[{}]:VMPROF_ENABLED:{}'.format(
                options.worker, outfn))

    def before_reactor_stopped():
        term_print('CROSSBAR[{}]:REACTOR_STOPPING'.format(options.worker))

        if _HAS_VMPROF and options.vmprof and _vm_prof['outfd']:
            vmprof.disable()
            term_print('CROSSBAR[{}]:VMPROF_DISABLED'.format(options.worker))

    def after_reactor_stopped():
        # FIXME: we are indeed reaching this line, however,
        # the log output does not work (it also doesnt work using
        # plain old print). Dunno why.

        # my theory about this issue is: by the time this line
        # is reached, Twisted has already closed the stdout/stderr
        # pipes. hence we do an evil trick: we directly write to
        # the process' controlling terminal
        # https://unix.stackexchange.com/a/91716/52500
        term_print('CROSSBAR[{}]:REACTOR_STOPPED'.format(options.worker))

    reactor.addSystemEventTrigger('before', 'startup', before_reactor_started)
    reactor.addSystemEventTrigger('after', 'startup', after_reactor_started)
    reactor.addSystemEventTrigger('before', 'shutdown', before_reactor_stopped)
    reactor.addSystemEventTrigger('after', 'shutdown', after_reactor_stopped)

    try:
        # define a WAMP application session factory
        #
        from autobahn.wamp.types import ComponentConfig

        def make_session():
            session_config = ComponentConfig(realm=options.realm,
                                             extra=options)
            session = klass(config=session_config,
                            reactor=reactor,
                            personality=Personality)
            return session

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(make_session,
                                                       'ws://localhost')
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.python.runtime import platform as _platform
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        if _platform.isWindows():
            stdio.StandardIO(proto)
        else:
            stdio.StandardIO(proto, stdout=3)

        # now start reactor loop
        #
        log.info(hl('Entering event reactor ...', color='green', bold=True))
        reactor.run()

    except Exception as e:
        log.info("Unhandled exception: {e}", e=e)
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #30
0
def run_command_version(options):
   """
   Subcommand "crossbar version".
   """
   reactor = install_reactor(options.reactor, options.debug)

   ## Python
   ##
   py_ver = '.'.join([str(x) for x in list(sys.version_info[:3])])
   if options.debug:
      py_ver += " [%s]" % sys.version.replace('\n', ' ')

   ## Twisted / Reactor
   ##
   tx_ver = "%s-%s" % (pkg_resources.require("Twisted")[0].version, reactor.__class__.__name__)
   if options.debug:
      tx_ver += " [%s]" % qual(reactor.__class__)

   ## Autobahn
   ##
   import autobahn
   from autobahn.websocket.protocol import WebSocketProtocol
   ab_ver = pkg_resources.require("autobahn")[0].version
   if options.debug:
      ab_ver += " [%s]" % qual(WebSocketProtocol)

   ## UTF8 Validator
   ##
   from autobahn.websocket.utf8validator import Utf8Validator
   s = str(Utf8Validator)
   if 'wsaccel' in s:
      utf8_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
   elif s.startswith('autobahn'):
      utf8_ver = 'autobahn'
   else:
      raise Exception("could not detect UTF8 validator type/version")
   if options.debug:
      utf8_ver += " [%s]" % qual(Utf8Validator)

   ## XOR Masker
   ##
   from autobahn.websocket.xormasker import XorMaskerNull
   s = str(XorMaskerNull)
   if 'wsaccel' in s:
      xor_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
   elif s.startswith('autobahn'):
      xor_ver = 'autobahn'
   else:
      raise Exception("could not detect XOR masker type/version")
   if options.debug:
      xor_ver += " [%s]" % qual(XorMaskerNull)

   import crossbar

   print("")
   print("Crossbar.io software versions:")
   print("")
   print("Crossbar.io     : {0}".format(crossbar.__version__))
   print("Autobahn        : {0}".format(ab_ver))
   print("Twisted         : {0}".format(tx_ver))
   print("Python          : {0}".format(py_ver))
   print("UTF8 Validator  : {0}".format(utf8_ver))
   print("XOR Masker      : {0}".format(xor_ver))
   print("")
Пример #31
0
    ##
    parser = argparse.ArgumentParser()

    parser.add_argument("-d", "--debug", action="store_true",
                        help="Enable debug output.")

    parser.add_argument("--endpoint", type=str, default="tcp:8080",
                        help='Twisted server endpoint descriptor, e.g. "tcp:8080" or "unix:/tmp/mywebsocket".')

    args = parser.parse_args()
    log.startLogging(sys.stdout)

    # we use an Autobahn utility to install the "best" available Twisted reactor
    ##
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor()
    print("Running on reactor {}".format(reactor))

    # create a WAMP router factory
    ##
    from autobahn.twisted.wamp import RouterFactory
    router_factory = RouterFactory()
    router_factory.router = MyRouter

    # create a WAMP router session factory
    ##
    from autobahn.twisted.wamp import RouterSessionFactory
    session_factory = RouterSessionFactory(router_factory)

    # create a WAMP-over-WebSocket transport server factory
    ##
Пример #32
0
def run_command_version(options):
   """
   Subcommand "crossbar version".
   """
   reactor = install_reactor(options.reactor, options.debug)

   ## Python
   ##
   py_ver = '.'.join([str(x) for x in list(sys.version_info[:3])])
   if options.debug:
      py_ver += " [%s]" % sys.version.replace('\n', ' ')

   ## Twisted / Reactor
   ##
   tx_ver = "%s-%s" % (pkg_resources.require("Twisted")[0].version, reactor.__class__.__name__)
   if options.debug:
      tx_ver += " [%s]" % qual(reactor.__class__)

   ## Autobahn
   ##
   import autobahn
   from autobahn.websocket.protocol import WebSocketProtocol
   ab_ver = pkg_resources.require("autobahn")[0].version
   if options.debug:
      ab_ver += " [%s]" % qual(WebSocketProtocol)

   ## UTF8 Validator
   ##
   from autobahn.websocket.utf8validator import Utf8Validator
   s = str(Utf8Validator)
   if 'wsaccel' in s:
      utf8_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
   elif s.startswith('autobahn'):
      utf8_ver = 'autobahn'
   else:
      # could not detect UTF8 validator type/version
      utf8_ver = '?'
   if options.debug:
      utf8_ver += " [%s]" % qual(Utf8Validator)

   ## XOR Masker
   ##
   from autobahn.websocket.xormasker import XorMaskerNull
   s = str(XorMaskerNull)
   if 'wsaccel' in s:
      xor_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
   elif s.startswith('autobahn'):
      xor_ver = 'autobahn'
   else:
      # could not detect XOR masker type/version
      xor_ver = '?'
   if options.debug:
      xor_ver += " [%s]" % qual(XorMaskerNull)

   ## JSON Serializer
   ##
   from autobahn.wamp.serializer import JsonObjectSerializer
   s = str(JsonObjectSerializer.JSON_MODULE)
   if 'ujson' in s:
      json_ver = 'ujson-%s' % pkg_resources.require('ujson')[0].version
   else:
      json_ver = 'stdlib'

   ## MsgPack Serializer
   ##
   try:
      import msgpack
      msgpack_ver = 'msgpack-python-%s' % pkg_resources.require('msgpack-python')[0].version
   except ImportError:
      msgpack_ver = '-'

   import crossbar
   import platform

   print("")
   print("Crossbar.io package versions and platform information:")
   print("")
   print("Crossbar.io                  : {0}".format(crossbar.__version__))
   print("")
   print("  Autobahn|Python            : {0}".format(ab_ver))
   print("    WebSocket UTF8 Validator : {0}".format(utf8_ver))
   print("    WebSocket XOR Masker     : {0}".format(xor_ver))
   print("    WAMP JSON Codec          : {0}".format(json_ver))
   print("    WAMP MsgPack Codec       : {0}".format(msgpack_ver))
   print("  Twisted                    : {0}".format(tx_ver))
   print("  Python                     : {0}-{1}".format(py_ver, platform.python_implementation()))
   print("")
   print("OS                           : {0}".format(platform.platform()))
   print("Machine                      : {0}".format(platform.machine()))
   print("")
Пример #33
0
def run(prog=None, args=None, reactor=None):
    """
    Entry point of Crossbar.io CLI.
    """
    loglevel_args = {
        "type": str,
        "default": 'info',
        "choices": ['none', 'error', 'warn', 'info', 'debug', 'trace'],
        "help": ("How much Crossbar.io should log to the terminal, in order "
                 "of verbosity.")
    }

    colour_args = {
        "type": str,
        "default": "auto",
        "choices": ["true", "false", "auto"],
        "help": "If logging should be coloured."
    }

    # create the top-level parser
    #
    parser = argparse.ArgumentParser(prog='crossbar',
                                     description="Crossbar.io - https://crossbar.io")

    # top-level options
    #
    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection')

    # create subcommand parser
    #
    subparsers = parser.add_subparsers(dest='command',
                                       title='commands',
                                       help='Crossbar.io command to run')
    subparsers.required = True

    # "version" command
    #
    parser_version = subparsers.add_parser('version',
                                           help='Print software versions.')

    parser_version.add_argument('--personality',
                                type=six.text_type,
                                default='community',
                                choices=get_defined_personalities(),
                                help=("Node personality to run."))

    parser_version.add_argument('--loglevel',
                                **loglevel_args)
    parser_version.add_argument('--colour',
                                **colour_args)

    parser_version.set_defaults(func=run_command_version)

    # "keys" command
    #
    parser_keys = subparsers.add_parser('keys',
                                        help='Print Crossbar.io release and node keys.')

    parser_keys.add_argument('--cbdir',
                             type=six.text_type,
                             default=None,
                             help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_keys.add_argument('--loglevel',
                             **loglevel_args)
    parser_keys.add_argument('--colour',
                             **colour_args)

    parser_keys.set_defaults(func=run_command_keys)

    # "init" command
    #
    parser_init = subparsers.add_parser('init',
                                        help='Initialize a new Crossbar.io node.')

    parser_init.set_defaults(func=run_command_init)

    parser_init.add_argument('--template',
                             type=six.text_type,
                             default='default',
                             help="Template for initialization")

    parser_init.add_argument('--appdir',
                             type=six.text_type,
                             default=None,
                             help="Application base directory where to create app and node from template.")

    # Start a worker
    #
    parser_worker = subparsers.add_parser('start-worker', help='Start a worker process')
    parser_worker = process.get_argument_parser(parser_worker)

    parser_worker.set_defaults(func=process.run)

    # "templates" command
    #
    parser_templates = subparsers.add_parser('templates',
                                             help='List templates available for initializing a new Crossbar.io node.')

    parser_templates.set_defaults(func=run_command_templates)

    # "start" command
    #
    parser_start = subparsers.add_parser('start',
                                         help='Start a Crossbar.io node.')

    parser_start.set_defaults(func=run_command_start)

    parser_start.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_start.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    parser_start.add_argument('--personality',
                              type=six.text_type,
                              default='community',
                              choices=get_defined_personalities(),
                              help=("Node personality to run."))

    parser_start.add_argument('--logdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io log directory (default: <Crossbar Node Directory>/)")

    parser_start.add_argument('--logtofile',
                              action='store_true',
                              help="Whether or not to log to file")

    parser_start.add_argument('--loglevel',
                              **loglevel_args)

    parser_start.add_argument('--colour',
                              **colour_args)

    parser_start.add_argument('--logformat',
                              type=six.text_type,
                              default='standard',
                              choices=['syslogd', 'standard', 'none'],
                              help=("The format of the logs -- suitable for "
                                    "syslogd, not coloured, or coloured."))

    # "stop" command
    #
    parser_stop = subparsers.add_parser('stop',
                                        help='Stop a Crossbar.io node.')

    parser_stop.add_argument('--cbdir',
                             type=six.text_type,
                             default=None,
                             help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_stop.set_defaults(func=run_command_stop)

    # "restart" command
    #
    parser_restart = subparsers.add_parser('restart',
                                           help='Restart a Crossbar.io node.')

    parser_restart.add_argument('--cbdir',
                                type=six.text_type,
                                default=None,
                                help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_restart.set_defaults(func=run_command_restart)

    # "status" command
    #
    parser_status = subparsers.add_parser('status',
                                          help='Checks whether a Crossbar.io node is running.')

    parser_status.add_argument('--cbdir',
                               type=six.text_type,
                               default=None,
                               help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_status.set_defaults(func=run_command_status)

    # "check" command
    #
    parser_check = subparsers.add_parser('check',
                                         help='Check a Crossbar.io node`s local configuration file.')

    parser_check.add_argument('--loglevel',
                              **loglevel_args)
    parser_check.add_argument('--colour',
                              **colour_args)
    parser_check.set_defaults(func=run_command_check)

    parser_check.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "convert" command
    #
    parser_check = subparsers.add_parser('convert',
                                         help='Convert a Crossbar.io node`s local configuration file from JSON to YAML or vice versa.')

    parser_check.set_defaults(func=run_command_convert)

    parser_check.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "upgrade" command
    #
    parser_check = subparsers.add_parser('upgrade',
                                         help='Upgrade a Crossbar.io node`s local configuration file to current configuration file format.')

    parser_check.set_defaults(func=run_command_upgrade)

    parser_check.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "keygen" command
    #
    help_text = 'Generate public/private keypairs for use with autobahn.wamp.cryptobox.KeyRing'
    parser_keygen = subparsers.add_parser(
        'keygen',
        help=help_text,
        description=help_text,
    )
    parser_keygen.set_defaults(func=run_command_keygen)

    # parse cmd line args
    #
    options = parser.parse_args(args)
    if args:
        options.argv = [prog] + args
    else:
        options.argv = sys.argv

    # coloured logging does not work on Windows, so overwrite it!
    #
    if sys.platform == 'win32':
        options.colour = False

    # IMPORTANT: keep the reactor install as early as possible to
    # avoid importing any Twisted module that comes with the side effect
    # of installing a default reactor (which might not be what we want!).
    if not reactor:
        # we use an Autobahn utility to import the "best" available Twisted reactor
        reactor = install_reactor(explicit_reactor=options.reactor,
                                  verbose=False,
                                  require_optimal_reactor=False)

    # ################## Twisted reactor installed FROM HERE ##################

    # Node personality
    #
    if hasattr(options, 'personality'):
        if options.personality not in get_installed_personalities():
            print('FATAL: no Crossbar.io node personality "{}" installed'.format(options.personality))
            sys.exit(1)

    # Crossbar.io node directory
    #
    if hasattr(options, 'cbdir'):
        if not options.cbdir:
            if "CROSSBAR_DIR" in os.environ:
                options.cbdir = os.environ['CROSSBAR_DIR']
            elif os.path.isdir('.crossbar'):
                options.cbdir = '.crossbar'
            else:
                options.cbdir = '.'

        options.cbdir = os.path.abspath(options.cbdir)

        # convenience: if --cbdir points to a config file, take
        # the config file's base dirname as node directory
        if os.path.isfile(options.cbdir):
            options.cbdir = os.path.dirname(options.cbdir)

        # convenience: auto-create directory if not existing
        if not os.path.isdir(options.cbdir):
            try:
                os.mkdir(options.cbdir)
            except Exception as e:
                print("Could not create node directory: {}".format(e))
                sys.exit(1)
            else:
                print("Auto-created node directory {}".format(options.cbdir))

    # Crossbar.io node configuration file
    #
    if hasattr(options, 'config'):
        # if not explicit config filename is given, try to auto-detect .
        if not options.config:
            for f in ['config.yaml', 'config.json']:
                fn = os.path.join(options.cbdir, f)
                if os.path.isfile(fn) and os.access(fn, os.R_OK):
                    options.config = f
                    break

    # Log directory
    #
    if hasattr(options, 'logdir'):
        if options.logdir:
            options.logdir = os.path.abspath(os.path.join(options.cbdir, options.logdir))
            if not os.path.isdir(options.logdir):
                try:
                    os.mkdir(options.logdir)
                except Exception as e:
                    print("Could not create log directory: {e}".format(e))
                    sys.exit(1)
                else:
                    print("Auto-created log directory {}".format(options.logdir))

    # Start the logger
    #
    _startlog(options, reactor)

    # run the subcommand selected
    #
    try:
        options.func(options, reactor=reactor)
    except SystemExit as e:
        # SystemExit(0) is okay! Anything other than that is bad and should be
        # re-raised.
        if e.args[0] != 0:
            raise
Пример #34
0
def run(prog=None, args=None, reactor=None):
    """
    Entry point of Crossbar.io CLI.
    """
    loglevel_args = {
        "type": str,
        "default": 'info',
        "choices": ['none', 'error', 'warn', 'info', 'debug', 'trace'],
        "help": ("How much Crossbar.io should log to the terminal, in order "
                 "of verbosity.")
    }

    colour_args = {
        "type": str,
        "default": "auto",
        "choices": ["true", "false", "auto"],
        "help": "If logging should be coloured."
    }

    # create the top-level parser
    #
    parser = argparse.ArgumentParser(prog='crossbar',
                                     description="Crossbar.io - Polyglot application router - http://crossbar.io")

    # top-level options
    #
    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection')

    # create subcommand parser
    #
    subparsers = parser.add_subparsers(dest='command',
                                       title='commands',
                                       help='Crossbar.io command to run')
    subparsers.required = True

    # "version" command
    #
    parser_version = subparsers.add_parser('version',
                                           help='Print software versions.')

    parser_version.add_argument('--loglevel',
                                **loglevel_args)
    parser_version.add_argument('--colour',
                                **colour_args)

    parser_version.set_defaults(func=run_command_version)

    # "init" command
    #
    parser_init = subparsers.add_parser('init',
                                        help='Initialize a new Crossbar.io node.')

    parser_init.set_defaults(func=run_command_init)

    parser_init.add_argument('--template',
                             type=six.text_type,
                             default='default',
                             help="Template for initialization")

    parser_init.add_argument('--appdir',
                             type=six.text_type,
                             default=None,
                             help="Application base directory where to create app and node from template.")

    # "templates" command
    #
    parser_templates = subparsers.add_parser('templates',
                                             help='List templates available for initializing a new Crossbar.io node.')

    parser_templates.set_defaults(func=run_command_templates)

    # "start" command
    #
    parser_start = subparsers.add_parser('start',
                                         help='Start a Crossbar.io node.')

    parser_start.set_defaults(func=run_command_start)

    parser_start.add_argument('--cdc',
                              action='store_true',
                              default=False,
                              help='Start node in managed mode, connecting to Crossbar.io DevOps Center (CDC).')

    parser_start.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_start.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    parser_start.add_argument('--logdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io log directory (default: <Crossbar Node Directory>/)")

    parser_start.add_argument('--logtofile',
                              action='store_true',
                              help="Whether or not to log to file")

    parser_start.add_argument('--loglevel',
                              **loglevel_args)

    parser_start.add_argument('--colour',
                              **colour_args)

    parser_start.add_argument('--logformat',
                              type=six.text_type,
                              default='standard',
                              choices=['syslogd', 'standard', 'none'],
                              help=("The format of the logs -- suitable for "
                                    "syslogd, not coloured, or coloured."))

    # "stop" command
    #
    parser_stop = subparsers.add_parser('stop',
                                        help='Stop a Crossbar.io node.')

    parser_stop.add_argument('--cbdir',
                             type=six.text_type,
                             default=None,
                             help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_stop.set_defaults(func=run_command_stop)

    # "restart" command
    #
    parser_restart = subparsers.add_parser('restart',
                                           help='Restart a Crossbar.io node.')

    parser_restart.add_argument('--cbdir',
                                type=six.text_type,
                                default=None,
                                help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_restart.set_defaults(func=run_command_restart)

    # "status" command
    #
    parser_status = subparsers.add_parser('status',
                                          help='Checks whether a Crossbar.io node is running.')

    parser_status.add_argument('--cbdir',
                               type=six.text_type,
                               default=None,
                               help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_status.set_defaults(func=run_command_status)

    # "check" command
    #
    parser_check = subparsers.add_parser('check',
                                         help='Check a Crossbar.io node`s local configuration file.')

    parser_check.add_argument('--loglevel',
                              **loglevel_args)
    parser_check.add_argument('--colour',
                              **colour_args)
    parser_check.set_defaults(func=run_command_check)

    parser_check.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "convert" command
    #
    parser_check = subparsers.add_parser('convert',
                                         help='Convert a Crossbar.io node`s local configuration file from JSON to YAML or vice versa.')

    parser_check.set_defaults(func=run_command_convert)

    parser_check.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "upgrade" command
    #
    parser_check = subparsers.add_parser('upgrade',
                                         help='Upgrade a Crossbar.io node`s local configuration file to current configuration file format.')

    parser_check.set_defaults(func=run_command_upgrade)

    parser_check.add_argument('--cbdir',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)")

    parser_check.add_argument('--config',
                              type=six.text_type,
                              default=None,
                              help="Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # parse cmd line args
    #
    options = parser.parse_args(args)
    if args:
        options.argv = [prog] + args
    else:
        options.argv = sys.argv

    # coloured logging does not work on Windows, so overwrite it!
    #
    if sys.platform == 'win32':
        options.colour = False

    # Crossbar.io node directory
    #
    if hasattr(options, 'cbdir'):
        if not options.cbdir:
            if "CROSSBAR_DIR" in os.environ:
                options.cbdir = os.environ['CROSSBAR_DIR']
            elif os.path.isdir('.crossbar'):
                options.cbdir = '.crossbar'
            else:
                options.cbdir = '.'
        options.cbdir = os.path.abspath(options.cbdir)

        # convenience: if --cbdir points to a config file, take
        # the config file's base dirname as node directory
        if os.path.isfile(options.cbdir):
            options.cbdir = os.path.dirname(options.cbdir)

    # Crossbar.io node configuration file
    #
    if hasattr(options, 'config'):
        # if not explicit config filename is given, try to auto-detect .
        if not options.config:
            for f in ['config.json', 'config.yaml']:
                fn = os.path.join(options.cbdir, f)
                if os.path.isfile(fn) and os.access(fn, os.R_OK):
                    options.config = f
                    break

            if not options.config:
                if options.cdc:
                    # in CDC mode, we will use a built-in default config
                    # if not overridden from explicit config file
                    pass
                else:
                    raise Exception("No config file specified, and neither CBDIR/config.json nor CBDIR/config.yaml exists")

    # Log directory
    #
    if hasattr(options, 'logdir'):
        if options.logdir:
            options.logdir = os.path.abspath(os.path.join(options.cbdir, options.logdir))
            if not os.path.isdir(options.logdir):
                try:
                    os.mkdir(options.logdir)
                except Exception as e:
                    print("Could not create log directory: {}".format(e))
                    sys.exit(1)

    if not reactor:
        # try and get the log verboseness we want -- not all commands have a
        # loglevel, so just default to info in that case
        debug = getattr(options, "loglevel", "info") in ("debug", "trace")

        # we use an Autobahn utility to import the "best" available Twisted
        # reactor
        reactor = install_reactor(options.reactor, debug)

    # Start the logger
    _startlog(options, reactor)

    # run the subcommand selected
    #
    try:
        options.func(options, reactor=reactor)
    except SystemExit as e:
        # SystemExit(0) is okay! Anything other than that is bad and should be
        # re-raised.
        if e.args[0] != 0:
            raise
Пример #35
0
def run_command_version(options):
    """
   Subcommand "crossbar version".
   """
    reactor = install_reactor(options.reactor, options.debug)

    ## Python
    ##
    py_ver = ".".join([str(x) for x in list(sys.version_info[:3])])
    if options.debug:
        py_ver += " [%s]" % sys.version.replace("\n", " ")

    ## Twisted / Reactor
    ##
    tx_ver = "%s-%s" % (pkg_resources.require("Twisted")[0].version, reactor.__class__.__name__)
    if options.debug:
        tx_ver += " [%s]" % qual(reactor.__class__)

    ## Autobahn
    ##
    import autobahn
    from autobahn.websocket.protocol import WebSocketProtocol

    ab_ver = pkg_resources.require("autobahn")[0].version
    if options.debug:
        ab_ver += " [%s]" % qual(WebSocketProtocol)

    ## UTF8 Validator
    ##
    from autobahn.websocket.utf8validator import Utf8Validator

    s = str(Utf8Validator)
    if "wsaccel" in s:
        utf8_ver = "wsaccel-%s" % pkg_resources.require("wsaccel")[0].version
    elif s.startswith("autobahn"):
        utf8_ver = "autobahn"
    else:
        raise Exception("could not detect UTF8 validator type/version")
    if options.debug:
        utf8_ver += " [%s]" % qual(Utf8Validator)

    ## XOR Masker
    ##
    from autobahn.websocket.xormasker import XorMaskerNull

    s = str(XorMaskerNull)
    if "wsaccel" in s:
        xor_ver = "wsaccel-%s" % pkg_resources.require("wsaccel")[0].version
    elif s.startswith("autobahn"):
        xor_ver = "autobahn"
    else:
        raise Exception("could not detect XOR masker type/version")
    if options.debug:
        xor_ver += " [%s]" % qual(XorMaskerNull)

    import crossbar

    print
    print "Crossbar.io software versions:"
    print
    print "Crossbar.io     : %s" % crossbar.__version__
    print "Autobahn        : %s" % ab_ver
    print "Twisted         : %s" % tx_ver
    print "Python          : %s" % py_ver
    print "UTF8 Validator  : %s" % utf8_ver
    print "XOR Masker      : %s" % xor_ver
    print
Пример #36
0
def run(prog=None, args=None, reactor=None):
    """
    Entry point of Crossbar.io CLI.
    """
    loglevel_args = {
        "type":
        str,
        "default":
        'info',
        "choices": ['none', 'error', 'warn', 'info', 'debug', 'trace'],
        "help": ("How much Crossbar.io should log to the terminal, in order "
                 "of verbosity.")
    }

    colour_args = {
        "type": str,
        "default": "auto",
        "choices": ["true", "false", "auto"],
        "help": "If logging should be coloured."
    }

    # create the top-level parser
    #
    parser = argparse.ArgumentParser(
        prog='crossbar',
        description=
        "Crossbar.io - Polyglot application router - http://crossbar.io")

    # top-level options
    #
    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection')

    # create subcommand parser
    #
    subparsers = parser.add_subparsers(dest='command',
                                       title='commands',
                                       help='Crossbar.io command to run')
    subparsers.required = True

    # "version" command
    #
    parser_version = subparsers.add_parser('version',
                                           help='Print software versions.')

    parser_version.add_argument('--loglevel', **loglevel_args)
    parser_version.add_argument('--colour', **colour_args)

    parser_version.set_defaults(func=run_command_version)

    # "init" command
    #
    parser_init = subparsers.add_parser(
        'init', help='Initialize a new Crossbar.io node.')

    parser_init.set_defaults(func=run_command_init)

    parser_init.add_argument('--template',
                             type=six.text_type,
                             default='default',
                             help="Template for initialization")

    parser_init.add_argument(
        '--appdir',
        type=six.text_type,
        default=None,
        help=
        "Application base directory where to create app and node from template."
    )

    # "templates" command
    #
    parser_templates = subparsers.add_parser(
        'templates',
        help='List templates available for initializing a new Crossbar.io node.'
    )

    parser_templates.set_defaults(func=run_command_templates)

    # "start" command
    #
    parser_start = subparsers.add_parser('start',
                                         help='Start a Crossbar.io node.')

    parser_start.set_defaults(func=run_command_start)

    parser_start.add_argument(
        '--cdc',
        action='store_true',
        default=False,
        help=
        'Start node in managed mode, connecting to Crossbar.io DevOps Center (CDC).'
    )

    parser_start.add_argument(
        '--cbdir',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)"
    )

    parser_start.add_argument(
        '--config',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io configuration file (overrides default CBDIR/config.json)")

    parser_start.add_argument(
        '--logdir',
        type=six.text_type,
        default=None,
        help="Crossbar.io log directory (default: <Crossbar Node Directory>/)")

    parser_start.add_argument('--logtofile',
                              action='store_true',
                              help="Whether or not to log to file")

    parser_start.add_argument('--loglevel', **loglevel_args)

    parser_start.add_argument('--colour', **colour_args)

    parser_start.add_argument('--logformat',
                              type=six.text_type,
                              default='standard',
                              choices=['syslogd', 'standard', 'none'],
                              help=("The format of the logs -- suitable for "
                                    "syslogd, not coloured, or coloured."))

    # "stop" command
    #
    parser_stop = subparsers.add_parser('stop',
                                        help='Stop a Crossbar.io node.')

    parser_stop.add_argument(
        '--cbdir',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)"
    )

    parser_stop.set_defaults(func=run_command_stop)

    # "restart" command
    #
    parser_restart = subparsers.add_parser('restart',
                                           help='Restart a Crossbar.io node.')

    parser_restart.add_argument(
        '--cbdir',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)"
    )

    parser_restart.set_defaults(func=run_command_restart)

    # "status" command
    #
    parser_status = subparsers.add_parser(
        'status', help='Checks whether a Crossbar.io node is running.')

    parser_status.add_argument(
        '--cbdir',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)"
    )

    parser_status.set_defaults(func=run_command_status)

    # "check" command
    #
    parser_check = subparsers.add_parser(
        'check', help='Check a Crossbar.io node`s local configuration file.')

    parser_check.add_argument('--loglevel', **loglevel_args)
    parser_check.add_argument('--colour', **colour_args)
    parser_check.set_defaults(func=run_command_check)

    parser_check.add_argument(
        '--cbdir',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)"
    )

    parser_check.add_argument(
        '--config',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "convert" command
    #
    parser_check = subparsers.add_parser(
        'convert',
        help=
        'Convert a Crossbar.io node`s local configuration file from JSON to YAML or vice versa.'
    )

    parser_check.set_defaults(func=run_command_convert)

    parser_check.add_argument(
        '--cbdir',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)"
    )

    parser_check.add_argument(
        '--config',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # "upgrade" command
    #
    parser_check = subparsers.add_parser(
        'upgrade',
        help=
        'Upgrade a Crossbar.io node`s local configuration file to current configuration file format.'
    )

    parser_check.set_defaults(func=run_command_upgrade)

    parser_check.add_argument(
        '--cbdir',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)"
    )

    parser_check.add_argument(
        '--config',
        type=six.text_type,
        default=None,
        help=
        "Crossbar.io configuration file (overrides default CBDIR/config.json)")

    # parse cmd line args
    #
    options = parser.parse_args(args)
    if args:
        options.argv = [prog] + args
    else:
        options.argv = sys.argv

    # coloured logging does not work on Windows, so overwrite it!
    #
    if sys.platform == 'win32':
        options.colour = False

    # Crossbar.io node directory
    #
    if hasattr(options, 'cbdir'):
        if not options.cbdir:
            if "CROSSBAR_DIR" in os.environ:
                options.cbdir = os.environ['CROSSBAR_DIR']
            elif os.path.isdir('.crossbar'):
                options.cbdir = '.crossbar'
            else:
                options.cbdir = '.'
        options.cbdir = os.path.abspath(options.cbdir)

    # Crossbar.io node configuration file
    #
    if hasattr(options, 'config'):
        # if not explicit config filename is given, try to auto-detect .
        if not options.config:
            for f in ['config.json', 'config.yaml']:
                fn = os.path.join(options.cbdir, f)
                if os.path.isfile(fn) and os.access(fn, os.R_OK):
                    options.config = f
                    break

            if not options.config:
                if options.cdc:
                    # in CDC mode, we will use a built-in default config
                    # if not overridden from explicit config file
                    pass
                else:
                    raise Exception(
                        "No config file specified, and neither CBDIR/config.json nor CBDIR/config.yaml exists"
                    )

    # Log directory
    #
    if hasattr(options, 'logdir'):
        if options.logdir:
            options.logdir = os.path.abspath(
                os.path.join(options.cbdir, options.logdir))
            if not os.path.isdir(options.logdir):
                try:
                    os.mkdir(options.logdir)
                except Exception as e:
                    print("Could not create log directory: {}".format(e))
                    sys.exit(1)

    if not reactor:
        # try and get the log verboseness we want -- not all commands have a
        # loglevel, so just default to info in that case
        debug = getattr(options, "loglevel", "info") in ("debug", "trace")

        # we use an Autobahn utility to import the "best" available Twisted
        # reactor
        reactor = install_reactor(options.reactor, debug)

    # Start the logger
    _startlog(options, reactor)

    # run the subcommand selected
    #
    try:
        options.func(options, reactor=reactor)
    except SystemExit as e:
        # SystemExit(0) is okay! Anything other than that is bad and should be
        # re-raised.
        if e.args[0] != 0:
            raise
Пример #37
0
def run_command_start(options):
    """
    Subcommand "crossbar start".
    """
    # do not allow to run more than one Crossbar.io instance
    # from the same Crossbar.io node directory
    #
    pid_data = check_is_running(options.cbdir)
    if pid_data:
        print("Crossbar.io is already running from node directory {} (PID {}).".format(options.cbdir, pid_data['pid']))
        sys.exit(1)
    else:
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        with open(fp, 'w') as fd:
            argv = options.argv
            options_dump = vars(options)
            del options_dump['func']
            del options_dump['argv']
            pid_data = {
                'pid': os.getpid(),
                'argv': argv,
                'options': options_dump
            }
            fd.write("{}\n".format(json.dumps(pid_data, sort_keys=False, indent=3, separators=(',', ': '))))

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    reactor = install_reactor(options.reactor, options.debug)

    # remove node PID file when reactor exits
    #
    def remove_pid_file():
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        if os.path.isfile(fp):
            os.remove(fp)
    reactor.addSystemEventTrigger('after', 'shutdown', remove_pid_file)

    # start Twisted logging
    #
    if not options.logdir:
        logfd = sys.stderr
    else:
        from twisted.python.logfile import DailyLogFile
        logfd = DailyLogFile.fromFullPath(os.path.join(options.logdir, 'node.log'))

    from crossbar.twisted.processutil import DefaultSystemFileLogObserver
    flo = DefaultSystemFileLogObserver(logfd, system="{:<10} {:>6}".format("Controller", os.getpid()))
    log.startLoggingWithObserver(flo.emit)

    log.msg("=" * 20 + " Crossbar.io " + "=" * 20 + "\n")

    import crossbar
    log.msg("Crossbar.io {} starting".format(crossbar.__version__))

    from twisted.python.reflect import qual
    log.msg("Running on {} using {} reactor".format(platform.python_implementation(), qual(reactor.__class__).split('.')[-1]))
    log.msg("Starting from node directory {}".format(options.cbdir))

    # create and start Crossbar.io node
    #
    from crossbar.controller.node import Node
    node = Node(reactor, options)
    node.start()

    try:
        log.msg("Entering reactor event loop ...")
        reactor.run()
    except Exception as e:
        log.msg("Could not start reactor: {0}".format(e))
Пример #38
0
def run_command_start(options):
    """
    Subcommand "crossbar start".
    """
    # do not allow to run more than one Crossbar.io instance
    # from the same Crossbar.io node directory
    #
    pid_data = check_is_running(options.cbdir)
    if pid_data:
        print(
            "Crossbar.io is already running from node directory {} (PID {}).".
            format(options.cbdir, pid_data['pid']))
        sys.exit(1)
    else:
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        with open(fp, 'w') as fd:
            argv = options.argv
            options_dump = vars(options)
            del options_dump['func']
            del options_dump['argv']
            pid_data = {
                'pid': os.getpid(),
                'argv': argv,
                'options': options_dump
            }
            fd.write("{}\n".format(
                json.dumps(pid_data,
                           sort_keys=False,
                           indent=3,
                           separators=(',', ': '))))

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    reactor = install_reactor(options.reactor, options.debug)

    # remove node PID file when reactor exits
    #
    def remove_pid_file():
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        if os.path.isfile(fp):
            os.remove(fp)

    reactor.addSystemEventTrigger('after', 'shutdown', remove_pid_file)

    # start Twisted logging
    #
    from crossbar._logging import log_publisher, make_logger
    from crossbar._logging import start_logging, set_global_log_level

    set_global_log_level(options.loglevel)

    log = make_logger()

    if options.logdir:
        # We want to log to a file
        from crossbar._logging import make_legacy_daily_logfile_observer

        log_publisher.addObserver(
            make_legacy_daily_logfile_observer(options.logdir,
                                               options.loglevel))
    else:
        # We want to log to stdout/stderr.
        from crossbar._logging import make_stdout_observer
        from crossbar._logging import make_stderr_observer

        if options.loglevel == "none":
            # Do no logging!
            pass
        elif options.loglevel == "error":
            # Error: Only print errors to stderr.
            log_publisher.addObserver(
                make_stdout_observer(show_source=False,
                                     format=options.logformat))
            log_publisher.addObserver(
                make_stderr_observer(show_source=False,
                                     format=options.logformat))
        elif options.loglevel == "warn":
            # Print warnings+ to stderr.
            log_publisher.addObserver(
                make_stdout_observer(show_source=False,
                                     format=options.logformat))
            log_publisher.addObserver(
                make_stderr_observer(show_source=False,
                                     format=options.logformat))
        elif options.loglevel == "info":
            # Print info to stdout, warn+ to stderr
            log_publisher.addObserver(
                make_stdout_observer(show_source=False,
                                     format=options.logformat))
            log_publisher.addObserver(
                make_stderr_observer(show_source=False,
                                     format=options.logformat))
        elif options.loglevel == "debug":
            # Print debug+info to stdout, warn+ to stderr, with the class
            # source
            log_publisher.addObserver(
                make_stdout_observer(show_source=True,
                                     format=options.logformat))
            log_publisher.addObserver(
                make_stderr_observer(show_source=True,
                                     format=options.logformat))
        elif options.loglevel == "trace":
            # Print trace+, with the class source
            log_publisher.addObserver(
                make_stdout_observer(show_source=True,
                                     format=options.logformat,
                                     trace=True))
            log_publisher.addObserver(
                make_stderr_observer(show_source=True,
                                     format=options.logformat))
        else:
            assert False, "Shouldn't ever get here."

    # Actually start the logger.
    start_logging()

    for line in BANNER.splitlines():
        log.info(click.style(("{:>40}").format(line), fg='yellow', bold=True))

    bannerFormat = "{:>12} {:<24}"
    log.info(
        bannerFormat.format(
            "Version:",
            click.style(crossbar.__version__, fg='yellow', bold=True)))
    # log.info(bannerFormat.format("Python:", click.style(platform.python_implementation(), fg='yellow', bold=True)))
    # log.info(bannerFormat.format("Reactor:", click.style(qual(reactor.__class__).split('.')[-1], fg='yellow', bold=True)))
    log.info(
        bannerFormat.format("Started:",
                            click.style(utcnow(), fg='yellow', bold=True)))
    log.info()

    log.info("Starting from node directory {}".format(options.cbdir))

    # create and start Crossbar.io node
    #
    def start_crossbar():
        from crossbar.controller.node import Node
        node = Node(reactor, options)
        d = node.start()

        def on_error(err):
            log.error("Could not start node: {error}", error=err.value)
            if reactor.running:
                reactor.stop()

        d.addErrback(on_error)

    reactor.callWhenRunning(start_crossbar)

    try:
        log.info("Entering reactor event loop...")
        reactor.run()
    except Exception:
        log.failure("Could not start reactor: {log_failure.value}")
Пример #39
0
def run():
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.

    def ignore(sig, frame):
        log.debug("Ignoring SIGINT in worker.")
    signal.signal(signal.SIGINT, ignore)

    # create the top-level parser
    #
    import argparse
    parser = argparse.ArgumentParser()

    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='Debug on (optional).')

    parser.add_argument('--reactor',
                        default=None,
                        choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'],
                        help='Explicit Twisted reactor selection (optional).')

    parser.add_argument('-c',
                        '--cbdir',
                        type=str,
                        help="Crossbar.io node directory (required).")

    parser.add_argument('-n',
                        '--node',
                        type=str,
                        help='Crossbar.io node ID (required).')

    parser.add_argument('-w',
                        '--worker',
                        type=str,
                        help='Crossbar.io worker ID (required).')

    parser.add_argument('-r',
                        '--realm',
                        type=str,
                        help='Crossbar.io node (management) realm (required).')

    parser.add_argument('-t',
                        '--type',
                        choices=['router', 'container'],
                        help='Worker type (required).')

    parser.add_argument('--title',
                        type=str,
                        default=None,
                        help='Worker process title to set (optional).')

    options = parser.parse_args()

    # make sure logging to something else than stdio is setup _first_
    #
    from twisted.logger import globalLogBeginner
    from crossbar._logging import Logger, make_JSON_observer

    log = Logger()
    _stderr = sys.stderr
    flo = make_JSON_observer(_stderr)
    globalLogBeginner.beginLoggingTo([flo])

    try:
        import setproctitle
    except ImportError:
        log.info("Warning: could not set worker process title (setproctitle not installed)")
    else:
        # set process title if requested to
        #
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            WORKER_TYPE_TO_TITLE = {
                'router': 'crossbar-worker [router]',
                'container': 'crossbar-worker [container]'
            }
            setproctitle.setproctitle(WORKER_TYPE_TO_TITLE[options.type].strip())

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    from twisted.python.reflect import qual
    log.info("Running under {python} using {reactor} reactor",
             python=platform.python_implementation(),
             reactor=qual(reactor.__class__).split('.')[-1])

    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    from crossbar.worker.router import RouterWorkerSession
    from crossbar.worker.container import ContainerWorkerSession

    WORKER_TYPE_TO_CLASS = {
        'router': RouterWorkerSession,
        'container': ContainerWorkerSession
    }

    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):

        def connectionLost(self, reason):
            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                log.warn("Connection to node controller lost.")
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                pass
            finally:
                # loosing the connection to the node controller is fatal:
                # stop the reactor and exit with error
                if reactor.running:
                    reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
                    reactor.stop()
                # if the reactor *isn't* running, we're already shutting down

    try:
        # create a WAMP application session factory
        #
        from autobahn.twisted.wamp import ApplicationSessionFactory
        from autobahn.wamp.types import ComponentConfig

        session_config = ComponentConfig(realm=options.realm, extra=options)
        session_factory = ApplicationSessionFactory(session_config)
        session_factory.session = WORKER_TYPE_TO_CLASS[options.type]

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug=False, debug_wamp=False)
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        stdio.StandardIO(proto)

        # now start reactor loop
        #
        log.info("Entering event loop...")
        reactor.run()

    except Exception as e:
        log.info("Unhandled exception: {}".format(e))
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #40
0
def _run_command_exec_worker(options, reactor=None, personality=None):
    """
    Entry point into (native) worker processes. This wires up stuff such that
    a worker instance is talking WAMP-over-stdio to the node controller.
    """
    import os
    import sys
    import platform
    import signal

    # https://coverage.readthedocs.io/en/coverage-4.4.2/subprocess.html#measuring-sub-processes
    MEASURING_COVERAGE = False
    if 'COVERAGE_PROCESS_START' in os.environ:
        try:
            import coverage
        except ImportError:
            pass
        else:
            # The following will read the environment variable COVERAGE_PROCESS_START,
            # and that should be set to the .coveragerc file:
            #
            #   export COVERAGE_PROCESS_START=${PWD}/.coveragerc
            #
            coverage.process_startup()
            MEASURING_COVERAGE = True

    # we use an Autobahn utility to import the "best" available Twisted reactor
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor(options.reactor)

    # make sure logging to something else than stdio is setup _first_
    from crossbar._logging import make_JSON_observer, cb_logging_aware
    from txaio import make_logger, start_logging
    from twisted.logger import globalLogPublisher
    from twisted.python.reflect import qual

    log = make_logger()

    # Print a magic phrase that tells the capturing logger that it supports
    # Crossbar's rich logging
    print(cb_logging_aware, file=sys.__stderr__)
    sys.__stderr__.flush()

    flo = make_JSON_observer(sys.__stderr__)
    globalLogPublisher.addObserver(flo)

    # Ignore SIGINT so we get consistent behavior on control-C versus
    # sending SIGINT to the controller process. When the controller is
    # shutting down, it sends TERM to all its children but ctrl-C
    # handling will send a SIGINT to all the processes in the group
    # (so then the controller sends a TERM but the child already or
    # will very shortly get a SIGINT as well). Twisted installs signal
    # handlers, but not for SIGINT if there's already a custom one
    # present.
    def ignore(sig, frame):
        log.debug("Ignoring SIGINT in worker.")
    signal.signal(signal.SIGINT, ignore)

    # actually begin logging
    start_logging(None, options.loglevel)

    # now check if we can import the requested personality
    Personality = crossbar.personalities().get(options.personality, None)
    if not Personality:
        raise Exception('logic error: personality "{}" not installed'.format(options.personality))

    # eg: crossbar.worker.container.ContainerController
    l = options.klass.split('.')
    worker_module, worker_klass = '.'.join(l[:-1]), l[-1]

    # now load the worker module and class
    _mod = importlib.import_module(worker_module)
    klass = getattr(_mod, worker_klass)

    log.info(
        'Starting worker "{worker_id}" for node "{node_id}" with personality "{personality}" {worker_class}',
        worker_id=options.worker,
        node_id=options.node,
        personality=Personality.NAME,
        worker_class=hltype(klass),
    )
    log.info(
        'Running as PID {pid} on {python}-{reactor}',
        pid=os.getpid(),
        python=platform.python_implementation(),
        reactor=qual(reactor.__class__).split('.')[-1],
    )
    if MEASURING_COVERAGE:
        log.info(hl('Code coverage measurements enabled (coverage={coverage_version}).', color='green', bold=True),
                 coverage_version=coverage.__version__)

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug("Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle('crossbar-worker [{}]'.format(options.klass))

    # node directory
    #
    options.cbdir = os.path.abspath(options.cbdir)
    os.chdir(options.cbdir)
    # log.msg("Starting from node directory {}".format(options.cbdir))

    # set process title if requested to
    #
    try:
        import setproctitle
    except ImportError:
        log.debug("Could not set worker process title (setproctitle not installed)")
    else:
        if options.title:
            setproctitle.setproctitle(options.title)
        else:
            setproctitle.setproctitle(
                'crossbar-worker [{}]'.format(options.klass)
            )

    from twisted.internet.error import ConnectionDone
    from autobahn.twisted.websocket import WampWebSocketServerProtocol

    class WorkerServerProtocol(WampWebSocketServerProtocol):

        def connectionLost(self, reason):
            # the behavior here differs slightly whether we're shutting down orderly
            # or shutting down because of "issues"
            if isinstance(reason.value, ConnectionDone):
                was_clean = True
            else:
                was_clean = False

            try:
                # this log message is unlikely to reach the controller (unless
                # only stdin/stdout pipes were lost, but not stderr)
                if was_clean:
                    log.info("Connection to node controller closed cleanly")
                else:
                    log.warn("Connection to node controller lost: {reason}", reason=reason)

                # give the WAMP transport a change to do it's thing
                WampWebSocketServerProtocol.connectionLost(self, reason)
            except:
                # we're in the process of shutting down .. so ignore ..
                pass
            finally:
                # after the connection to the node controller is gone,
                # the worker is "orphane", and should exit

                # determine process exit code
                if was_clean:
                    exit_code = 0
                else:
                    exit_code = 1

                # exit the whole worker process when the reactor has stopped
                reactor.addSystemEventTrigger('after', 'shutdown', os._exit, exit_code)

                # stop the reactor
                try:
                    reactor.stop()
                except ReactorNotRunning:
                    pass

    try:
        # define a WAMP application session factory
        #
        from autobahn.wamp.types import ComponentConfig

        def make_session():
            session_config = ComponentConfig(realm=options.realm, extra=options)
            session = klass(config=session_config, reactor=reactor, personality=Personality)
            return session

        # create a WAMP-over-WebSocket transport server factory
        #
        from autobahn.twisted.websocket import WampWebSocketServerFactory
        transport_factory = WampWebSocketServerFactory(make_session, u'ws://localhost')
        transport_factory.protocol = WorkerServerProtocol
        transport_factory.setProtocolOptions(failByDrop=False)

        # create a protocol instance and wire up to stdio
        #
        from twisted.python.runtime import platform as _platform
        from twisted.internet import stdio
        proto = transport_factory.buildProtocol(None)
        if _platform.isWindows():
            stdio.StandardIO(proto)
        else:
            stdio.StandardIO(proto, stdout=3)

        # now start reactor loop
        #
        if False:
            log.info("vmprof enabled.")

            import os
            import vmprof

            PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid())

            outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
            vmprof.enable(outfd, period=0.01)

            log.info(hl('Entering event reactor ...', color='cyan', bold=True))
            reactor.run()

            vmprof.disable()
        else:
            log.info(hl('Entering event reactor ...', color='cyan', bold=True))
            reactor.run()

    except Exception as e:
        log.info("Unhandled exception: {e}", e=e)
        if reactor.running:
            reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1)
            reactor.stop()
        else:
            sys.exit(1)
Пример #41
0
def run_command_version(options):
    """
    Subcommand "crossbar version".
    """
    reactor = install_reactor(options.reactor, options.debug)

    # Python
    #
    py_ver = '.'.join([str(x) for x in list(sys.version_info[:3])])
    if options.debug:
        py_ver += " [%s]" % sys.version.replace('\n', ' ')

    if 'pypy_version_info' in sys.__dict__:
        py_ver_detail = "{}-{}".format(platform.python_implementation(), '.'.join(str(x) for x in sys.pypy_version_info[:3]))
    else:
        py_ver_detail = platform.python_implementation()

    # Twisted / Reactor
    #
    tx_ver = "%s-%s" % (pkg_resources.require("Twisted")[0].version, reactor.__class__.__name__)
    if options.debug:
        tx_ver += " [%s]" % qual(reactor.__class__)

    # Autobahn
    #
    from autobahn.websocket.protocol import WebSocketProtocol
    ab_ver = pkg_resources.require("autobahn")[0].version
    if options.debug:
        ab_ver += " [%s]" % qual(WebSocketProtocol)

    # UTF8 Validator
    #
    from autobahn.websocket.utf8validator import Utf8Validator
    s = qual(Utf8Validator)
    if 'wsaccel' in s:
        utf8_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
    elif s.startswith('autobahn'):
        utf8_ver = 'autobahn'
    else:
        # could not detect UTF8 validator type/version
        utf8_ver = '?'
    if options.debug:
        utf8_ver += " [%s]" % qual(Utf8Validator)

    # XOR Masker
    #
    from autobahn.websocket.xormasker import XorMaskerNull
    s = qual(XorMaskerNull)
    if 'wsaccel' in s:
        xor_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
    elif s.startswith('autobahn'):
        xor_ver = 'autobahn'
    else:
        # could not detect XOR masker type/version
        xor_ver = '?'
    if options.debug:
        xor_ver += " [%s]" % qual(XorMaskerNull)

    # JSON Serializer
    #
    from autobahn.wamp.serializer import JsonObjectSerializer
    s = str(JsonObjectSerializer.JSON_MODULE)
    if 'ujson' in s:
        json_ver = 'ujson-%s' % pkg_resources.require('ujson')[0].version
    else:
        json_ver = 'stdlib'

    # MsgPack Serializer
    #
    try:
        import msgpack  # noqa
        msgpack_ver = 'msgpack-python-%s' % pkg_resources.require('msgpack-python')[0].version
    except ImportError:
        msgpack_ver = '-'

    for line in BANNER.splitlines():
        print(click.style(("{:>40}").format(line), fg='yellow', bold=True))

    print("Crossbar.io        : {0}".format(click.style(crossbar.__version__, fg='yellow', bold=True)))
    print("  Autobahn         : {0}".format(click.style(ab_ver, fg='yellow', bold=True)))
    print("    UTF8 Validator : {0}".format(click.style(utf8_ver, fg='yellow', bold=True)))
    print("    XOR Masker     : {0}".format(click.style(xor_ver, fg='yellow', bold=True)))
    print("    JSON Codec     : {0}".format(click.style(json_ver, fg='yellow', bold=True)))
    print("    MsgPack Codec  : {0}".format(click.style(msgpack_ver, fg='yellow', bold=True)))
    print("  Twisted          : {0}".format(click.style(tx_ver, fg='yellow', bold=True)))
    print("  Python           : {0}/{1}".format(click.style(py_ver, fg='yellow', bold=True), click.style(py_ver_detail, fg='yellow', bold=True)))
    print("OS                 : {0}".format(click.style(platform.platform(), fg='yellow', bold=True)))
    print("Machine            : {0}".format(click.style(platform.machine(), fg='yellow', bold=True)))
    print("")
Пример #42
0
def run_command_version(options):
   """
   Subcommand "crossbar version".
   """
   reactor = install_reactor(options.reactor, options.debug)

   ## Python
   ##
   py_ver = '.'.join([str(x) for x in list(sys.version_info[:3])])
   if options.debug:
      py_ver += " [%s]" % sys.version.replace('\n', ' ')

   ## Twisted / Reactor
   ##
   tx_ver = "%s-%s" % (pkg_resources.require("Twisted")[0].version, reactor.__class__.__name__)
   if options.debug:
      tx_ver += " [%s]" % qual(reactor.__class__)

   ## Autobahn
   ##
   import autobahn
   from autobahn.websocket.protocol import WebSocketProtocol
   ab_ver = pkg_resources.require("autobahn")[0].version
   if options.debug:
      ab_ver += " [%s]" % qual(WebSocketProtocol)

   ## UTF8 Validator
   ##
   from autobahn.websocket.utf8validator import Utf8Validator
   s = str(Utf8Validator)
   if 'wsaccel' in s:
      utf8_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
   elif s.startswith('autobahn'):
      utf8_ver = 'autobahn'
   else:
      raise Exception("could not detect UTF8 validator type/version")
   if options.debug:
      utf8_ver += " [%s]" % qual(Utf8Validator)

   ## XOR Masker
   ##
   from autobahn.websocket.xormasker import XorMaskerNull
   s = str(XorMaskerNull)
   if 'wsaccel' in s:
      xor_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
   elif s.startswith('autobahn'):
      xor_ver = 'autobahn'
   else:
      raise Exception("could not detect XOR masker type/version")
   if options.debug:
      xor_ver += " [%s]" % qual(XorMaskerNull)

   import crossbar

   print("")
   print("Crossbar.io software versions:")
   print("")
   print("Crossbar.io     : {0}".format(crossbar.__version__))
   print("Autobahn        : {0}".format(ab_ver))
   print("Twisted         : {0}".format(tx_ver))
   print("Python          : {0}".format(py_ver))
   print("UTF8 Validator  : {0}".format(utf8_ver))
   print("XOR Masker      : {0}".format(xor_ver))
   print("")
Пример #43
0
def run_command_start(options):
    """
    Subcommand "crossbar start".
    """
    # do not allow to run more than one Crossbar.io instance
    # from the same Crossbar.io node directory
    #
    pid_data = check_is_running(options.cbdir)
    if pid_data:
        print("Crossbar.io is already running from node directory {} (PID {}).".format(options.cbdir, pid_data['pid']))
        sys.exit(1)
    else:
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        with open(fp, 'w') as fd:
            argv = options.argv
            options_dump = vars(options)
            del options_dump['func']
            del options_dump['argv']
            pid_data = {
                'pid': os.getpid(),
                'argv': argv,
                'options': options_dump
            }
            fd.write("{}\n".format(json.dumps(pid_data, sort_keys=False, indent=3, separators=(',', ': '))))

    # we use an Autobahn utility to import the "best" available Twisted reactor
    #
    reactor = install_reactor(options.reactor, options.debug)

    # remove node PID file when reactor exits
    #
    def remove_pid_file():
        fp = os.path.join(options.cbdir, _PID_FILENAME)
        if os.path.isfile(fp):
            os.remove(fp)
    reactor.addSystemEventTrigger('after', 'shutdown', remove_pid_file)

    # start Twisted logging
    #
    from crossbar._logging import log_publisher, make_logger
    from crossbar._logging import start_logging, set_global_log_level

    set_global_log_level(options.loglevel)

    log = make_logger()

    if options.logdir:
        # We want to log to a file
        from crossbar._logging import make_legacy_daily_logfile_observer

        log_publisher.addObserver(
            make_legacy_daily_logfile_observer(options.logdir, options.loglevel))
    else:
        # We want to log to stdout/stderr.
        from crossbar._logging import make_stdout_observer
        from crossbar._logging import make_stderr_observer

        if options.loglevel == "none":
            # Do no logging!
            pass
        elif options.loglevel == "error":
            # Error: Only print errors to stderr.
            log_publisher.addObserver(make_stdout_observer(show_source=False, format=options.logformat))
            log_publisher.addObserver(make_stderr_observer(show_source=False, format=options.logformat))
        elif options.loglevel == "warn":
            # Print warnings+ to stderr.
            log_publisher.addObserver(make_stdout_observer(show_source=False, format=options.logformat))
            log_publisher.addObserver(make_stderr_observer(show_source=False, format=options.logformat))
        elif options.loglevel == "info":
            # Print info to stdout, warn+ to stderr
            log_publisher.addObserver(make_stdout_observer(show_source=False, format=options.logformat))
            log_publisher.addObserver(make_stderr_observer(show_source=False, format=options.logformat))
        elif options.loglevel == "debug":
            # Print debug+info to stdout, warn+ to stderr, with the class
            # source
            log_publisher.addObserver(make_stdout_observer(show_source=True, format=options.logformat))
            log_publisher.addObserver(make_stderr_observer(show_source=True, format=options.logformat))
        elif options.loglevel == "trace":
            # Print trace+, with the class source
            log_publisher.addObserver(make_stdout_observer(show_source=True, format=options.logformat, trace=True))
            log_publisher.addObserver(make_stderr_observer(show_source=True, format=options.logformat))
        else:
            assert False, "Shouldn't ever get here."

    # Actually start the logger.
    start_logging()

    for line in BANNER.splitlines():
        log.info(click.style(("{:>40}").format(line), fg='yellow', bold=True))

    bannerFormat = "{:>12} {:<24}"
    log.info(bannerFormat.format("Version:", click.style(crossbar.__version__, fg='yellow', bold=True)))
    # log.info(bannerFormat.format("Python:", click.style(platform.python_implementation(), fg='yellow', bold=True)))
    # log.info(bannerFormat.format("Reactor:", click.style(qual(reactor.__class__).split('.')[-1], fg='yellow', bold=True)))
    log.info(bannerFormat.format("Started:", click.style(utcnow(), fg='yellow', bold=True)))
    log.info()

    log.info("Starting from node directory {}".format(options.cbdir))

    # create and start Crossbar.io node
    #
    def start_crossbar():
        from crossbar.controller.node import Node
        node = Node(reactor, options)
        d = node.start()

        def on_error(err):
            log.error("Could not start node: {error}", error=err.value)
            if reactor.running:
                reactor.stop()
        d.addErrback(on_error)
    reactor.callWhenRunning(start_crossbar)

    try:
        log.info("Entering reactor event loop...")
        reactor.run()
    except Exception:
        log.failure("Could not start reactor: {log_failure.value}")
Пример #44
0
    parser.add_argument(
        "--endpoint",
        type=str,
        default="tcp:8080",
        help=
        'Twisted server endpoint descriptor, e.g. "tcp:8080" or "unix:/tmp/mywebsocket".'
    )

    args = parser.parse_args()
    log.startLogging(sys.stdout)

    ## we use an Autobahn utility to install the "best" available Twisted reactor
    ##
    from autobahn.twisted.choosereactor import install_reactor
    reactor = install_reactor()
    print("Running on reactor {}".format(reactor))

    ## create a WAMP router factory
    ##
    from autobahn.twisted.wamp import RouterFactory
    router_factory = RouterFactory()

    ## create a WAMP router session factory
    ##
    from autobahn.twisted.wamp import RouterSessionFactory
    session_factory = RouterSessionFactory(router_factory)

    ## create a WAMP-over-WebSocket transport server factory
    ##
    from autobahn.twisted.websocket import WampWebSocketServerFactory
Пример #45
0
def run_command_version(options):
    """
    Subcommand "crossbar version".
    """
    reactor = install_reactor(options.reactor, options.debug)

    # Python
    #
    py_ver = '.'.join([str(x) for x in list(sys.version_info[:3])])
    if options.debug:
        py_ver += " [%s]" % sys.version.replace('\n', ' ')

    # Twisted / Reactor
    #
    tx_ver = "%s-%s" % (pkg_resources.require("Twisted")[0].version, reactor.__class__.__name__)
    if options.debug:
        tx_ver += " [%s]" % qual(reactor.__class__)

    # Autobahn
    #
    from autobahn.websocket.protocol import WebSocketProtocol
    ab_ver = pkg_resources.require("autobahn")[0].version
    if options.debug:
        ab_ver += " [%s]" % qual(WebSocketProtocol)

    # UTF8 Validator
    #
    from autobahn.websocket.utf8validator import Utf8Validator
    s = str(Utf8Validator)
    if 'wsaccel' in s:
        utf8_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
    elif s.startswith('autobahn'):
        utf8_ver = 'autobahn'
    else:
        # could not detect UTF8 validator type/version
        utf8_ver = '?'
    if options.debug:
        utf8_ver += " [%s]" % qual(Utf8Validator)

    # XOR Masker
    #
    from autobahn.websocket.xormasker import XorMaskerNull
    s = str(XorMaskerNull)
    if 'wsaccel' in s:
        xor_ver = 'wsaccel-%s' % pkg_resources.require('wsaccel')[0].version
    elif s.startswith('autobahn'):
        xor_ver = 'autobahn'
    else:
        # could not detect XOR masker type/version
        xor_ver = '?'
    if options.debug:
        xor_ver += " [%s]" % qual(XorMaskerNull)

    # JSON Serializer
    #
    from autobahn.wamp.serializer import JsonObjectSerializer
    s = str(JsonObjectSerializer.JSON_MODULE)
    if 'ujson' in s:
        json_ver = 'ujson-%s' % pkg_resources.require('ujson')[0].version
    else:
        json_ver = 'stdlib'

    # MsgPack Serializer
    #
    try:
        import msgpack  # noqa
        msgpack_ver = 'msgpack-python-%s' % pkg_resources.require('msgpack-python')[0].version
    except ImportError:
        msgpack_ver = '-'

    import crossbar
    import platform

    print("")
    print("Crossbar.io package versions and platform information:")
    print("")
    print("Crossbar.io                  : {0}".format(crossbar.__version__))
    print("")
    print("  Autobahn|Python            : {0}".format(ab_ver))
    print("    WebSocket UTF8 Validator : {0}".format(utf8_ver))
    print("    WebSocket XOR Masker     : {0}".format(xor_ver))
    print("    WAMP JSON Codec          : {0}".format(json_ver))
    print("    WAMP MsgPack Codec       : {0}".format(msgpack_ver))
    print("  Twisted                    : {0}".format(tx_ver))
    print("  Python                     : {0}-{1}".format(py_ver, platform.python_implementation()))
    print("")
    print("OS                           : {0}".format(platform.platform()))
    print("Machine                      : {0}".format(platform.machine()))
    print("")