def add_realm_to_router(router_factory, session_factory, realm_name=u'default', realm_options={}): opts = dict(realm_options) opts.update({u'name': realm_name}) # start a realm realm = RouterRealm(None, opts) router = router_factory.start_realm(realm) extra = {} session_config = ComponentConfig(realm_name, extra) realm.session = RouterServiceSession(session_config, router) # allow everything default_permissions = { u'uri': u'', u'match': u'prefix', u'allow': { u'call': True, u'register': True, u'publish': True, u'subscribe': True } } router = router_factory.get(realm_name) router.add_role(RouterRoleStaticAuth(router, 'anonymous', default_permissions=default_permissions)) session_factory.add(realm.session, authrole=u'trusted') return router
def setUp(self): """ Setup router and router session factories. """ # create a router factory self.router_factory = RouterFactory(u'mynode') # start a realm self.router_factory.start_realm(RouterRealm(None, {u'name': u'realm1'})) # allow everything default_permissions = { u'uri': u'', u'match': u'prefix', u'allow': { u'call': True, u'register': True, u'publish': True, u'subscribe': True } } self.router = self.router_factory.get(u'realm1') self.router.add_role(RouterRoleStaticAuth(self.router, u'test_role', default_permissions=default_permissions)) self.router.add_role(RouterRoleStaticAuth(self.router, None, default_permissions=default_permissions)) # create a router session factory self.session_factory = RouterSessionFactory(self.router_factory)
def setUp(self): # create a router factory self.router_factory = RouterFactory(None, None) # start a realm self.realm = RouterRealm(None, {u'name': u'realm1'}) self.router_factory.start_realm(self.realm) # allow everything self.router = self.router_factory.get(u'realm1') self.router.add_role( RouterRoleStaticAuth(self.router, u'test_role', default_permissions={ u'uri': u'com.myapp.', u'match': u'prefix', u'allow': { u'call': True, u'register': True, u'publish': True, u'subscribe': True, } })) # create a router session factory self.session_factory = RouterSessionFactory(self.router_factory)
def make_router(realm_name=u'default'): """ Make a router, and return it and a RawSocket factory. """ # create a router factory router_factory = RouterFactory() # start a realm realm = RouterRealm(None, {u'name': realm_name}) router = router_factory.start_realm(realm) extra = {} session_config = ComponentConfig(realm_name, extra) realm.session = RouterServiceSession(session_config, router) # allow everything default_permissions = { u'uri': u'', u'match': u'prefix', u'allow': { u'call': True, u'register': True, u'publish': True, u'subscribe': True } } router = router_factory.get(realm_name) router.add_role(RouterRoleStaticAuth(router, 'anonymous', default_permissions=default_permissions)) # create a router session factory session_factory = RouterSessionFactory(router_factory) session_factory.add(realm.session, authrole=u'trusted') # Create a new RawSocket factory server_factory = WampRawSocketServerFactory(session_factory, {}) return router, server_factory
def setUp(self): """ Setup router and router session factories. """ # create a router factory self.router_factory = RouterFactory() # start a realm self.router_factory.start_realm(RouterRealm(None, {u'name': u'realm1'})) # allow everything permissions = RouterPermissions('', True, True, True, True, True) router = self.router_factory.get(u'realm1') router.add_role(RouterRoleStaticAuth(router, None, default_permissions=permissions)) # create a router session factory self.session_factory = RouterSessionFactory(self.router_factory)
def start(self): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ # for now, a node is always started from a local configuration # configfile = os.path.join(self.options.cbdir, self.options.config) self.log.info("Starting from node configuration file '{configfile}'", configfile=configfile) self._config = check_config_file(configfile, silence=True) controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) controller_title = controller_options.get('title', 'crossbar-controller') try: import setproctitle except ImportError: self.log.warn("Warning, could not set process title (setproctitle not installed)") else: setproctitle.setproctitle(controller_title) # the node's name (must be unique within the management realm) if 'manager' in self._config: self._node_id = self._config['manager']['id'] else: if 'id' in controller_config: self._node_id = controller_config['id'] else: self._node_id = socket.gethostname() if 'manager' in self._config: extra = { 'onready': Deferred() } runner = ApplicationRunner(url=u"ws://localhost:9000", realm=u"cdc-oberstet-1", extra=extra) runner.run(NodeManagementSession, start_reactor=False) # wait until we have attached to the uplink CDC self._management_session = yield extra['onready'] self.log.info("Connected to Crossbar.io Management Cloud: {management_session}", management_session=self._management_session) else: self._management_session = None # the node's management realm self._realm = controller_config.get('realm', 'crossbar') # router and factory that creates router sessions # self._router_factory = RouterFactory() self._router_session_factory = RouterSessionFactory(self._router_factory) rlm = RouterRealm(None, {'name': self._realm}) # create a new router for the realm router = self._router_factory.start_realm(rlm) # add a router/realm service session cfg = ComponentConfig(self._realm) rlm.session = RouterServiceSession(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') if self._management_session: self._bridge_session = NodeManagementBridgeSession(cfg, self._management_session) self._router_session_factory.add(self._bridge_session, authrole=u'trusted') else: self._bridge_session = None # the node controller singleton WAMP application session # # session_config = ComponentConfig(realm = options.realm, extra = options) self._controller = NodeControllerSession(self) # add the node controller singleton session to the router # self._router_session_factory.add(self._controller, authrole=u'trusted') # Detect WAMPlets # wamplets = self._controller._get_wamplets() if len(wamplets) > 0: self.log.info("Detected {wamplets} WAMPlets in environment:", wamplets=len(wamplets)) for wpl in wamplets: self.log.info("WAMPlet {dist}.{name}", dist=wpl['dist'], name=wpl['name']) else: self.log.info("No WAMPlets detected in enviroment.") try: if 'manager' in self._config: yield self._startup_managed(self._config) else: yield self._startup_standalone(self._config) except: traceback.print_exc() try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self, cdc_mode=False): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: raise Exception("No node configuration loaded") if not cdc_mode and not self._config.get( "controller", {}) and not self._config.get("workers", {}): self.log.warn( ("You seem to have no controller config or workers, nor are " "starting up in CDC mode. Check your config exists, or pass " "--cdc to `crossbar start`.")) try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass return # get controller config/options # controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) # set controller process title # try: import setproctitle except ImportError: self.log.warn( "Warning, could not set process title (setproctitle not installed)" ) else: setproctitle.setproctitle( controller_options.get('title', 'crossbar-controller')) # router and factory that creates router sessions # self._router_factory = RouterFactory() self._router_session_factory = RouterSessionFactory( self._router_factory) # create a new router for the realm # rlm_config = {'name': self._realm} rlm = RouterRealm(None, rlm_config) router = self._router_factory.start_realm(rlm) # always add a realm service session # cfg = ComponentConfig(self._realm) rlm.session = RouterServiceSession(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') # add a router bridge session when running in managed mode # if cdc_mode: self._bridge_session = NodeManagementBridgeSession(cfg) self._router_session_factory.add(self._bridge_session, authrole=u'trusted') else: self._bridge_session = None # Node shutdown mode # if cdc_mode: # in managed mode, a node - by default - only shuts down when explicitly asked to, # or upon a fatal error in the node controller self._node_shutdown_triggers = [ checkconfig.NODE_SHUTDOWN_ON_SHUTDOWN_REQUESTED ] else: # in standalone mode, a node - by default - is immediately shutting down whenever # a worker exits (successfully or with error) self._node_shutdown_triggers = [ checkconfig.NODE_SHUTDOWN_ON_WORKER_EXIT ] # allow to override node shutdown triggers # if 'shutdown' in controller_options: self.log.info( "Overriding default node shutdown triggers with {triggers} from node config", triggers=controller_options['shutdown']) self._node_shutdown_triggers = controller_options['shutdown'] else: self.log.info("Using default node shutdown triggers {triggers}", triggers=self._node_shutdown_triggers) # add the node controller singleton session # self._controller = NodeControllerSession(self) self._router_session_factory.add(self._controller, authrole=u'trusted') # detect WAMPlets (FIXME: remove this!) # wamplets = self._controller._get_wamplets() if len(wamplets) > 0: self.log.info("Detected {wamplets} WAMPlets in environment:", wamplets=len(wamplets)) for wpl in wamplets: self.log.info("WAMPlet {dist}.{name}", dist=wpl['dist'], name=wpl['name']) else: self.log.debug("No WAMPlets detected in enviroment.") panic = False try: # startup the node from local node configuration # yield self._startup(self._config) # connect to CDC when running in managed mode # if cdc_mode: cdc_config = controller_config.get( 'cdc', { # CDC connecting transport u'transport': { u'type': u'websocket', u'url': u'wss://cdc.crossbario.com/ws', u'endpoint': { u'type': u'tcp', u'host': u'cdc.crossbario.com', u'port': 443, u'timeout': 5, u'tls': { u'hostname': u'cdc.crossbario.com' } } } }) transport = cdc_config[u'transport'] hostname = None if u'tls' in transport[u'endpoint']: transport[u'endpoint'][u'tls'][u'hostname'] runner = ApplicationRunner( url=transport['url'], realm=None, extra=None, ssl=optionsForClientTLS(hostname) if hostname else None, ) def make(config): # extra info forwarded to CDC client session extra = { 'node': self, 'on_ready': Deferred(), 'on_exit': Deferred(), 'node_key': self._node_key, } @inlineCallbacks def on_ready(res): self._manager, self._management_realm, self._node_id, self._node_extra = res if self._bridge_session: try: yield self._bridge_session.attach_manager( self._manager, self._management_realm, self._node_id) status = yield self._manager.call( u'cdc.remote.status@1') except: self.log.failure() else: self.log.info( 'Connected to CDC for management realm "{realm}" (current time is {now})', realm=self._management_realm, now=status[u'now']) else: self.log.warn( 'Uplink CDC session established, but no bridge session setup!' ) @inlineCallbacks def on_exit(res): if self._bridge_session: try: yield self._bridge_session.detach_manager() except: self.log.failure() else: self.log.info( 'Disconnected from CDC for management realm "{realm}"', realm=self._management_realm) else: self.log.warn( 'Uplink CDC session lost, but no bridge session setup!' ) self._manager, self._management_realm, self._node_id, self._node_extra = None, None, None, None extra['on_ready'].addCallback(on_ready) extra['on_exit'].addCallback(on_exit) config = ComponentConfig(extra=extra) session = NodeManagementSession(config) return session self.log.info("Connecting to CDC at '{url}' ..", url=transport[u'url']) yield runner.run(make, start_reactor=False, auto_reconnect=True) # Notify systemd that crossbar is fully up and running # (this has no effect on non-systemd platforms) try: import sdnotify sdnotify.SystemdNotifier().notify("READY=1") except: pass except ApplicationError as e: panic = True self.log.error("{msg}", msg=e.error_message()) except Exception: panic = True traceback.print_exc() if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: raise Exception("No node configuration set") # get controller config/options # controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) # set controller process title # try: import setproctitle except ImportError: self.log.warn("Warning, could not set process title (setproctitle not installed)") else: setproctitle.setproctitle(controller_options.get('title', 'crossbar-controller')) # local node management router # self._router_factory = RouterFactory(self._node_id, None) self._router_session_factory = RouterSessionFactory(self._router_factory) rlm_config = { 'name': self._realm } rlm = RouterRealm(None, rlm_config) router = self._router_factory.start_realm(rlm) # setup global static roles # self._add_global_roles() # always add a realm service session # cfg = ComponentConfig(self._realm) rlm.session = (self.ROUTER_SERVICE)(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') self.log.debug('Router service session attached [{router_service}]', router_service=qual(self.ROUTER_SERVICE)) # add the node controller singleton component # self._controller = self.NODE_CONTROLLER(self) self._router_session_factory.add(self._controller, authrole=u'trusted') self.log.debug('Node controller attached [{node_controller}]', node_controller=qual(self.NODE_CONTROLLER)) # add extra node controller components # self._add_extra_controller_components(controller_options) # setup Node shutdown triggers # self._set_shutdown_triggers(controller_options) panic = False try: # startup the node personality .. yield self._startup() # .. and notify systemd that we are fully up and running try: import sdnotify sdnotify.SystemdNotifier().notify("READY=1") except: # do nothing on non-systemd platforms pass except ApplicationError as e: panic = True self.log.error("{msg}", msg=e.error_message()) except Exception: panic = True self.log.failure() self.log.error('fatal: could not startup node') if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self, cdc_mode=False): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: raise Exception("No node configuration loaded") controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) # set controller process title # try: import setproctitle except ImportError: self.log.warn( "Warning, could not set process title (setproctitle not installed)" ) else: setproctitle.setproctitle( controller_options.get('title', 'crossbar-controller')) # the node controller realm # self._realm = controller_config.get('realm', 'crossbar') # the node's name (must be unique within the management realm when running # in "managed mode") # if 'id' in controller_config: self._node_id = controller_config['id'] self.log.info("Node ID '{node_id}' set from config", node_id=self._node_id) elif 'CDC_ID' in os.environ: self._node_id = u'{}'.format(os.environ['CDC_ID']) self.log.info( "Node ID '{node_id}' set from environment variable CDC_ID", node_id=self._node_id) else: self._node_id = u'{}'.format(socket.gethostname()) self.log.info("Node ID '{node_id}' set from hostname", node_id=self._node_id) # standalone vs managed mode # if 'cdc' in controller_config and controller_config['cdc'].get( 'enabled', False): self._prepare_node_keys() cdc_config = controller_config['cdc'] # CDC connecting transport # if 'transport' in cdc_config: transport = cdc_config['transport'] if 'tls' in transport['endpoint']: hostname = transport['endpoint']['tls']['hostname'] else: raise Exception( "TLS activated on CDC connection, but 'hostname' not provided" ) self.log.warn( "CDC transport configuration overridden from node config!") else: transport = { "type": u"websocket", "url": u"wss://devops.crossbario.com/ws", "endpoint": { "type": u"tcp", "host": u"devops.crossbario.com", "port": 443, "timeout": 5, "tls": { "hostname": u"devops.crossbario.com" } } } hostname = u'devops.crossbario.com' # CDC management realm # if 'realm' in cdc_config: realm = cdc_config['realm'] self.log.info("CDC management realm '{realm}' set from config", realm=realm) elif 'CDC_REALM' in os.environ: realm = u"{}".format(os.environ['CDC_REALM']).strip() self.log.info( "CDC management realm '{realm}' set from enviroment variable CDC_REALM", realm=realm) else: raise Exception( "CDC management realm not set - either 'realm' must be set in node configuration, or in CDC_REALM enviroment variable" ) # CDC authentication credentials (for WAMP-CRA) # authid = self._node_id if 'secret' in cdc_config: authkey = cdc_config['secret'] self.log.info("CDC authentication secret loaded from config") elif 'CDC_SECRET' in os.environ: authkey = u"{}".format(os.environ['CDC_SECRET']).strip() self.log.info( "CDC authentication secret loaded from environment variable CDC_SECRET" ) else: raise Exception( "CDC authentication secret not set - either 'secret' must be set in node configuration, or in CDC_SECRET enviroment variable" ) # extra info forwarded to CDC client session # extra = { 'node': self, 'onready': Deferred(), 'onexit': Deferred(), 'authid': authid, 'authkey': authkey } runner = ApplicationRunner( url=transport['url'], realm=realm, extra=extra, ssl=optionsForClientTLS(hostname), debug=False, debug_wamp=False, ) try: self.log.info("Connecting to CDC at '{url}' ..", url=transport['url']) yield runner.run(NodeManagementSession, start_reactor=False) # wait until we have attached to the uplink CDC self._manager = yield extra['onready'] except Exception as e: raise Exception("Could not connect to CDC - {}".format(e)) # in managed mode, a node - by default - only shuts down when explicitly asked to, # or upon a fatal error in the node controller self._node_shutdown_triggers = [ checkconfig.NODE_SHUTDOWN_ON_SHUTDOWN_REQUESTED ] self.log.info( "Connected to Crossbar.io DevOps Center (CDC)! Your node runs in managed mode." ) else: self._manager = None # in standalone mode, a node - by default - is immediately shutting down whenever # a worker exits (successfully or with error) self._node_shutdown_triggers = [ checkconfig.NODE_SHUTDOWN_ON_WORKER_EXIT ] # allow to override node shutdown triggers # if 'shutdown' in controller_options: self.log.info( "Overriding default node shutdown triggers with {} from node config" .format(controller_options['shutdown'])) self._node_shutdown_triggers = controller_options['shutdown'] else: self.log.info("Using default node shutdown triggers {}".format( self._node_shutdown_triggers)) # router and factory that creates router sessions # self._router_factory = RouterFactory(self._node_id) self._router_session_factory = RouterSessionFactory( self._router_factory) rlm_config = {'name': self._realm} rlm = RouterRealm(None, rlm_config) # create a new router for the realm router = self._router_factory.start_realm(rlm) # add a router/realm service session cfg = ComponentConfig(self._realm) rlm.session = RouterServiceSession(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') if self._manager: self._bridge_session = NodeManagementBridgeSession( cfg, self, self._manager) self._router_session_factory.add(self._bridge_session, authrole=u'trusted') else: self._bridge_session = None # the node controller singleton WAMP application session # self._controller = NodeControllerSession(self) # add the node controller singleton session to the router # self._router_session_factory.add(self._controller, authrole=u'trusted') # Detect WAMPlets # wamplets = self._controller._get_wamplets() if len(wamplets) > 0: self.log.info("Detected {wamplets} WAMPlets in environment:", wamplets=len(wamplets)) for wpl in wamplets: self.log.info("WAMPlet {dist}.{name}", dist=wpl['dist'], name=wpl['name']) else: self.log.debug("No WAMPlets detected in enviroment.") panic = False try: yield self._startup(self._config) except ApplicationError as e: panic = True self.log.error("{msg}", msg=e.error_message()) except Exception: panic = True traceback.print_exc() if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: self.check_config() controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) controller_title = controller_options.get('title', 'crossbar-controller') try: import setproctitle except ImportError: self.log.warn("Warning, could not set process title (setproctitle not installed)") else: setproctitle.setproctitle(controller_title) # the node's name (must be unique within the management realm) if 'id' in controller_config: self._node_id = controller_config['id'] else: self._node_id = socket.gethostname() if 'manager' in controller_config: extra = { 'onready': Deferred(), # authentication information for connecting to uplinkg CDC router # using WAMP-CRA authentication # 'authid': self._node_id, 'authkey': controller_config['manager']['key'] } realm = controller_config['manager']['realm'] transport = controller_config['manager']['transport'] runner = ApplicationRunner(url=transport['url'], realm=realm, extra=extra, debug_wamp=False) runner.run(NodeManagementSession, start_reactor=False) # wait until we have attached to the uplink CDC self._management_session = yield extra['onready'] self.log.info("Node is connected to Crossbar.io DevOps Center (CDC)") else: self._management_session = None # the node's management realm self._realm = controller_config.get('realm', 'crossbar') # router and factory that creates router sessions # self._router_factory = RouterFactory() self._router_session_factory = RouterSessionFactory(self._router_factory) rlm_config = { 'name': self._realm } rlm = RouterRealm(None, rlm_config) # create a new router for the realm router = self._router_factory.start_realm(rlm) # add a router/realm service session cfg = ComponentConfig(self._realm) rlm.session = RouterServiceSession(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') if self._management_session: self._bridge_session = NodeManagementBridgeSession(cfg, self._management_session) self._router_session_factory.add(self._bridge_session, authrole=u'trusted') else: self._bridge_session = None # the node controller singleton WAMP application session # self._controller = NodeControllerSession(self) # add the node controller singleton session to the router # self._router_session_factory.add(self._controller, authrole=u'trusted') # Detect WAMPlets # wamplets = self._controller._get_wamplets() if len(wamplets) > 0: self.log.info("Detected {wamplets} WAMPlets in environment:", wamplets=len(wamplets)) for wpl in wamplets: self.log.info("WAMPlet {dist}.{name}", dist=wpl['dist'], name=wpl['name']) else: self.log.info("No WAMPlets detected in enviroment.") panic = False try: yield self._startup(self._config) except ApplicationError as e: panic = True for line in e.args[0].strip().splitlines(): self.log.error(line) except Exception: panic = True traceback.print_exc() if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: raise Exception("No node configuration set") # get controller config/options # controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) # set controller process title # try: import setproctitle except ImportError: self.log.warn( "Warning, could not set process title (setproctitle not installed)" ) else: setproctitle.setproctitle( controller_options.get('title', 'crossbar-controller')) # local node management router # self._router_factory = RouterFactory() self._router_session_factory = RouterSessionFactory( self._router_factory) rlm_config = {'name': self._realm} rlm = RouterRealm(None, rlm_config) router = self._router_factory.start_realm(rlm) # setup global static roles # self._add_global_roles() # always add a realm service session # cfg = ComponentConfig(self._realm) rlm.session = (self.ROUTER_SERVICE)(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') self.log.debug('Router service session attached [{router_service}]', router_service=qual(self.ROUTER_SERVICE)) # add the node controller singleton component # self._controller = self.NODE_CONTROLLER(self) self._router_session_factory.add(self._controller, authrole=u'trusted') self.log.debug('Node controller attached [{node_controller}]', node_controller=qual(self.NODE_CONTROLLER)) # add extra node controller components # self._add_extra_controller_components(controller_options) # setup Node shutdown triggers # self._set_shutdown_triggers(controller_options) panic = False try: # startup the node personality .. yield self._startup() # .. and notify systemd that we are fully up and running try: import sdnotify sdnotify.SystemdNotifier().notify("READY=1") except: # do nothing on non-systemd platforms pass except ApplicationError as e: panic = True self.log.error("{msg}", msg=e.error_message()) except Exception: panic = True self.log.failure('Could not startup node: {log_failure.value}') if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self, cdc_mode=False): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: raise Exception("No node configuration loaded") controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) # set controller process title # try: import setproctitle except ImportError: self.log.warn("Warning, could not set process title (setproctitle not installed)") else: setproctitle.setproctitle(controller_options.get('title', 'crossbar-controller')) # the node controller realm # self._realm = controller_config.get(u'realm', u'crossbar') # the node's name (must be unique within the management realm when running # in "managed mode") # if 'id' in controller_config: self._node_id = controller_config['id'] self.log.info("Node ID '{node_id}' set from config", node_id=self._node_id) elif 'CDC_ID' in os.environ: self._node_id = u'{}'.format(os.environ['CDC_ID']) self.log.info("Node ID '{node_id}' set from environment variable CDC_ID", node_id=self._node_id) else: self._node_id = u'{}'.format(socket.gethostname()) self.log.info("Node ID '{node_id}' set from hostname", node_id=self._node_id) # standalone vs managed mode # if 'cdc' in controller_config and controller_config['cdc'].get('enabled', False): self._prepare_node_keys() cdc_config = controller_config['cdc'] # CDC connecting transport # if 'transport' in cdc_config: transport = cdc_config['transport'] if 'tls' in transport['endpoint']: if 'hostname' in transport['endpoint']: hostname = transport['endpoint']['tls']['hostname'] else: raise Exception("TLS activated on CDC connection, but 'hostname' not provided") else: hostname = None self.log.warn("CDC transport configuration overridden from node config!") else: transport = { "type": u"websocket", "url": u"wss://devops.crossbario.com/ws", "endpoint": { "type": u"tcp", "host": u"devops.crossbario.com", "port": 443, "timeout": 5, "tls": { "hostname": u"devops.crossbario.com" } } } hostname = u'devops.crossbario.com' # CDC management realm # if 'realm' in cdc_config: realm = cdc_config['realm'] self.log.info("CDC management realm '{realm}' set from config", realm=realm) elif 'CDC_REALM' in os.environ: realm = u"{}".format(os.environ['CDC_REALM']).strip() self.log.info("CDC management realm '{realm}' set from enviroment variable CDC_REALM", realm=realm) else: raise Exception("CDC management realm not set - either 'realm' must be set in node configuration, or in CDC_REALM enviroment variable") # CDC authentication credentials (for WAMP-CRA) # authid = self._node_id if 'secret' in cdc_config: authkey = cdc_config['secret'] self.log.info("CDC authentication secret loaded from config") elif 'CDC_SECRET' in os.environ: authkey = u"{}".format(os.environ['CDC_SECRET']).strip() self.log.info("CDC authentication secret loaded from environment variable CDC_SECRET") else: raise Exception("CDC authentication secret not set - either 'secret' must be set in node configuration, or in CDC_SECRET enviroment variable") # extra info forwarded to CDC client session # extra = { 'node': self, 'onready': Deferred(), 'onexit': Deferred(), 'authid': authid, 'authkey': authkey } runner = ApplicationRunner( url=transport['url'], realm=realm, extra=extra, ssl=optionsForClientTLS(hostname) if hostname else None, ) try: self.log.info("Connecting to CDC at '{url}' ..", url=transport['url']) yield runner.run(NodeManagementSession, start_reactor=False) # wait until we have attached to the uplink CDC self._manager = yield extra['onready'] except Exception as e: raise Exception("Could not connect to CDC - {}".format(e)) # in managed mode, a node - by default - only shuts down when explicitly asked to, # or upon a fatal error in the node controller self._node_shutdown_triggers = [checkconfig.NODE_SHUTDOWN_ON_SHUTDOWN_REQUESTED] self.log.info("Connected to Crossbar.io DevOps Center (CDC)! Your node runs in managed mode.") else: self._manager = None # in standalone mode, a node - by default - is immediately shutting down whenever # a worker exits (successfully or with error) self._node_shutdown_triggers = [checkconfig.NODE_SHUTDOWN_ON_WORKER_EXIT] # allow to override node shutdown triggers # if 'shutdown' in controller_options: self.log.info("Overriding default node shutdown triggers with {} from node config".format(controller_options['shutdown'])) self._node_shutdown_triggers = controller_options['shutdown'] else: self.log.info("Using default node shutdown triggers {}".format(self._node_shutdown_triggers)) # router and factory that creates router sessions # self._router_factory = RouterFactory(self._node_id) self._router_session_factory = RouterSessionFactory(self._router_factory) rlm_config = { 'name': self._realm } rlm = RouterRealm(None, rlm_config) # create a new router for the realm router = self._router_factory.start_realm(rlm) # add a router/realm service session cfg = ComponentConfig(self._realm) rlm.session = RouterServiceSession(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') if self._manager: self._bridge_session = NodeManagementBridgeSession(cfg, self, self._manager) self._router_session_factory.add(self._bridge_session, authrole=u'trusted') else: self._bridge_session = None # the node controller singleton WAMP application session # self._controller = NodeControllerSession(self) # add the node controller singleton session to the router # self._router_session_factory.add(self._controller, authrole=u'trusted') # Detect WAMPlets # wamplets = self._controller._get_wamplets() if len(wamplets) > 0: self.log.info("Detected {wamplets} WAMPlets in environment:", wamplets=len(wamplets)) for wpl in wamplets: self.log.info("WAMPlet {dist}.{name}", dist=wpl['dist'], name=wpl['name']) else: self.log.debug("No WAMPlets detected in enviroment.") panic = False try: yield self._startup(self._config) # Notify systemd that crossbar is fully up and running # This has no effect on non-systemd platforms try: import sdnotify sdnotify.SystemdNotifier().notify("READY=1") except: pass except ApplicationError as e: panic = True self.log.error("{msg}", msg=e.error_message()) except Exception: panic = True traceback.print_exc() if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: self.check_config() controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) controller_title = controller_options.get('title', 'crossbar-controller') try: import setproctitle except ImportError: self.log.warn( "Warning, could not set process title (setproctitle not installed)" ) else: setproctitle.setproctitle(controller_title) # the node's name (must be unique within the management realm) if 'id' in controller_config: self._node_id = controller_config['id'] else: self._node_id = socket.gethostname() if 'manager' in controller_config: extra = { 'onready': Deferred(), # authentication information for connecting to uplinkg CDC router # using WAMP-CRA authentication # 'authid': self._node_id, 'authkey': controller_config['manager']['key'] } realm = controller_config['manager']['realm'] transport = controller_config['manager']['transport'] runner = ApplicationRunner(url=transport['url'], realm=realm, extra=extra, debug_wamp=False) runner.run(NodeManagementSession, start_reactor=False) # wait until we have attached to the uplink CDC self._management_session = yield extra['onready'] self.log.info( "Node is connected to Crossbar.io DevOps Center (CDC)") else: self._management_session = None # the node's management realm self._realm = controller_config.get('realm', 'crossbar') # router and factory that creates router sessions # self._router_factory = RouterFactory() self._router_session_factory = RouterSessionFactory( self._router_factory) rlm = RouterRealm(None, {'name': self._realm}) # create a new router for the realm router = self._router_factory.start_realm(rlm) # add a router/realm service session cfg = ComponentConfig(self._realm) rlm.session = RouterServiceSession(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') if self._management_session: self._bridge_session = NodeManagementBridgeSession( cfg, self._management_session) self._router_session_factory.add(self._bridge_session, authrole=u'trusted') else: self._bridge_session = None # the node controller singleton WAMP application session # self._controller = NodeControllerSession(self) # add the node controller singleton session to the router # self._router_session_factory.add(self._controller, authrole=u'trusted') # Detect WAMPlets # wamplets = self._controller._get_wamplets() if len(wamplets) > 0: self.log.info("Detected {wamplets} WAMPlets in environment:", wamplets=len(wamplets)) for wpl in wamplets: self.log.info("WAMPlet {dist}.{name}", dist=wpl['dist'], name=wpl['name']) else: self.log.info("No WAMPlets detected in enviroment.") panic = False try: yield self._startup(self._config) except ApplicationError as e: panic = True for line in e.args[0].strip().splitlines(): self.log.error(line) except Exception: panic = True traceback.print_exc() if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass
def start(self, cdc_mode=False): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. """ if not self._config: raise Exception("No node configuration loaded") if not cdc_mode and not self._config.get("controller", {}) and not self._config.get("workers", {}): self.log.warn( ("You seem to have no controller config or workers, nor are " "starting up in CDC mode. Check your config exists, or pass " "--cdc to `crossbar start`.")) try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass return # get controller config/options # controller_config = self._config.get('controller', {}) controller_options = controller_config.get('options', {}) # set controller process title # try: import setproctitle except ImportError: self.log.warn("Warning, could not set process title (setproctitle not installed)") else: setproctitle.setproctitle(controller_options.get('title', 'crossbar-controller')) # router and factory that creates router sessions # self._router_factory = RouterFactory() self._router_session_factory = RouterSessionFactory(self._router_factory) # create a new router for the realm # rlm_config = { 'name': self._realm } rlm = RouterRealm(None, rlm_config) router = self._router_factory.start_realm(rlm) # always add a realm service session # cfg = ComponentConfig(self._realm) rlm.session = RouterServiceSession(cfg, router) self._router_session_factory.add(rlm.session, authrole=u'trusted') # add a router bridge session when running in managed mode # if cdc_mode: self._bridge_session = NodeManagementBridgeSession(cfg) self._router_session_factory.add(self._bridge_session, authrole=u'trusted') else: self._bridge_session = None # Node shutdown mode # if cdc_mode: # in managed mode, a node - by default - only shuts down when explicitly asked to, # or upon a fatal error in the node controller self._node_shutdown_triggers = [checkconfig.NODE_SHUTDOWN_ON_SHUTDOWN_REQUESTED] else: # in standalone mode, a node - by default - is immediately shutting down whenever # a worker exits (successfully or with error) self._node_shutdown_triggers = [checkconfig.NODE_SHUTDOWN_ON_WORKER_EXIT] # allow to override node shutdown triggers # if 'shutdown' in controller_options: self.log.info("Overriding default node shutdown triggers with {triggers} from node config", triggers=controller_options['shutdown']) self._node_shutdown_triggers = controller_options['shutdown'] else: self.log.info("Using default node shutdown triggers {triggers}", triggers=self._node_shutdown_triggers) # add the node controller singleton session # self._controller = NodeControllerSession(self) self._router_session_factory.add(self._controller, authrole=u'trusted') # detect WAMPlets (FIXME: remove this!) # wamplets = self._controller._get_wamplets() if len(wamplets) > 0: self.log.info("Detected {wamplets} WAMPlets in environment:", wamplets=len(wamplets)) for wpl in wamplets: self.log.info("WAMPlet {dist}.{name}", dist=wpl['dist'], name=wpl['name']) else: self.log.debug("No WAMPlets detected in enviroment.") panic = False try: # startup the node from local node configuration # yield self._startup(self._config) # connect to CDC when running in managed mode # if cdc_mode: cdc_config = controller_config.get('cdc', { # CDC connecting transport u'transport': { u'type': u'websocket', u'url': u'wss://cdc.crossbario.com/ws', u'endpoint': { u'type': u'tcp', u'host': u'cdc.crossbario.com', u'port': 443, u'timeout': 5, u'tls': { u'hostname': u'cdc.crossbario.com' } } } }) transport = cdc_config[u'transport'] hostname = None if u'tls' in transport[u'endpoint']: transport[u'endpoint'][u'tls'][u'hostname'] runner = ApplicationRunner( url=transport['url'], realm=None, extra=None, ssl=optionsForClientTLS(hostname) if hostname else None, ) def make(config): # extra info forwarded to CDC client session extra = { 'node': self, 'on_ready': Deferred(), 'on_exit': Deferred(), 'node_key': self._node_key, } @inlineCallbacks def on_ready(res): self._manager, self._management_realm, self._node_id, self._node_extra = res if self._bridge_session: try: yield self._bridge_session.attach_manager(self._manager, self._management_realm, self._node_id) status = yield self._manager.call(u'cdc.remote.status@1') except: self.log.failure() else: self.log.info('Connected to CDC for management realm "{realm}" (current time is {now})', realm=self._management_realm, now=status[u'now']) else: self.log.warn('Uplink CDC session established, but no bridge session setup!') @inlineCallbacks def on_exit(res): if self._bridge_session: try: yield self._bridge_session.detach_manager() except: self.log.failure() else: self.log.info('Disconnected from CDC for management realm "{realm}"', realm=self._management_realm) else: self.log.warn('Uplink CDC session lost, but no bridge session setup!') self._manager, self._management_realm, self._node_id, self._node_extra = None, None, None, None extra['on_ready'].addCallback(on_ready) extra['on_exit'].addCallback(on_exit) config = ComponentConfig(extra=extra) session = NodeManagementSession(config) return session self.log.info("Connecting to CDC at '{url}' ..", url=transport[u'url']) yield runner.run(make, start_reactor=False, auto_reconnect=True) # Notify systemd that crossbar is fully up and running # (this has no effect on non-systemd platforms) try: import sdnotify sdnotify.SystemdNotifier().notify("READY=1") except: pass except ApplicationError as e: panic = True self.log.error("{msg}", msg=e.error_message()) except Exception: panic = True traceback.print_exc() if panic: try: self._reactor.stop() except twisted.internet.error.ReactorNotRunning: pass