def start_manhole(self, config, details=None): """ Start a Manhole service within this process. **Usage:** This procedure is registered under * ``crossbar.node.<node_id>.worker.<worker_id>.start_manhole`` - for native workers * ``crossbar.node.<node_id>.controller.start_manhole`` - for node controllers The procedure takes a Manhole service configuration which defines a listening endpoint for the service and a list of users including passwords, e.g. .. code-block:: javascript { "endpoint": { "type": "tcp", "port": 6022 }, "users": [ { "user": "******", "password": "******" } ] } **Errors:** The procedure may raise the following errors: * ``crossbar.error.invalid_configuration`` - the provided configuration is invalid * ``crossbar.error.already_started`` - the Manhole service is already running (or starting) * ``crossbar.error.feature_unavailable`` - the required support packages are not installed **Events:** The procedure will publish an event when the service **is starting** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_starting`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_starting`` - for node controllers and publish an event when the service **has started** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_started`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_started`` - for node controllers :param config: Manhole service configuration. :type config: dict """ self.log.debug("{cls}.start_manhole(config = {config})", cls=self.__class__.__name__, config=config) if not _HAS_MANHOLE: emsg = "Could not start manhole: required packages are missing ({})".format( _MANHOLE_MISSING_REASON) self.log.error(emsg) raise ApplicationError(u"crossbar.error.feature_unavailable", emsg) if self._manhole_service: emsg = "Could not start manhole - already running (or starting)" self.log.warn(emsg) raise ApplicationError(u"crossbar.error.already_started", emsg) try: checkconfig.check_manhole(config) except Exception as e: emsg = "Could not start manhole: invalid configuration ({})".format( e) self.log.error(emsg) raise ApplicationError(u'crossbar.error.invalid_configuration', emsg) # setup user authentication # checker = checkers.InMemoryUsernamePasswordDatabaseDontUse() for user in config['users']: checker.addUser(user['user'], user['password']) # setup manhole namespace # namespace = {'session': self} from twisted.conch.manhole_ssh import (ConchFactory, TerminalRealm, TerminalSession) from twisted.conch.manhole import ColoredManhole class PatchedTerminalSession(TerminalSession): # get rid of # exceptions.AttributeError: TerminalSession instance has no attribute 'windowChanged' def windowChanged(self, winSize): pass rlm = TerminalRealm() rlm.sessionFactory = PatchedTerminalSession # monkey patch rlm.chainedProtocolFactory.protocolFactory = lambda _: ColoredManhole( namespace) ptl = portal.Portal(rlm, [checker]) factory = ConchFactory(ptl) factory.noisy = False self._manhole_service = ManholeService(config, details.caller) starting_topic = '{}.on_manhole_starting'.format(self._uri_prefix) starting_info = self._manhole_service.marshal() # the caller gets a progressive result .. if details.progress: details.progress(starting_info) # .. while all others get an event self.publish(starting_topic, starting_info, options=PublishOptions(exclude=details.caller)) try: self._manhole_service.port = yield create_listening_port_from_config( config['endpoint'], self.cbdir, factory, self._reactor, self.log) except Exception as e: self._manhole_service = None emsg = "Manhole service endpoint cannot listen: {}".format(e) self.log.error(emsg) raise ApplicationError(u"crossbar.error.cannot_listen", emsg) # alright, manhole has started self._manhole_service.started = datetime.utcnow() self._manhole_service.status = 'started' started_topic = '{}.on_manhole_started'.format(self._uri_prefix) started_info = self._manhole_service.marshal() self.publish(started_topic, started_info, options=PublishOptions(exclude=details.caller)) returnValue(started_info)
def start_manhole(self, config, details=None): """ Start a manhole (SSH) within this worker. :param config: Manhole configuration. :type config: obj """ if self.debug: log.msg("{}.start_manhole".format(self.__class__.__name__), config) if not _HAS_MANHOLE: emsg = "ERROR: could not start manhole - required packages are missing ({})".format( _MANHOLE_MISSING_REASON) log.msg(emsg) raise ApplicationError("crossbar.error.feature_unavailable", emsg) if self._manhole_service: emsg = "ERROR: could not start manhole - already running (or starting)" log.msg(emsg) raise ApplicationError("crossbar.error.already_started", emsg) try: checkconfig.check_manhole(config) except Exception as e: emsg = "ERROR: could not start manhole - invalid configuration ({})".format( e) log.msg(emsg) raise ApplicationError('crossbar.error.invalid_configuration', emsg) # setup user authentication # checker = checkers.InMemoryUsernamePasswordDatabaseDontUse() for user in config['users']: checker.addUser(user['user'], user['password']) # setup manhole namespace # namespace = {'session': self} class PatchedTerminalSession(TerminalSession): # get rid of # exceptions.AttributeError: TerminalSession instance has no attribute 'windowChanged' def windowChanged(self, winSize): pass rlm = TerminalRealm() rlm.sessionFactory = PatchedTerminalSession # monkey patch rlm.chainedProtocolFactory.protocolFactory = lambda _: ColoredManhole( namespace) ptl = portal.Portal(rlm, [checker]) factory = ConchFactory(ptl) factory.noisy = False self._manhole_service = ManholeService(config, details.caller) starting_topic = '{}.on_manhole_starting'.format(self._uri_prefix) starting_info = self._manhole_service.marshal() # the caller gets a progressive result .. if details.progress: details.progress(starting_info) # .. while all others get an event self.publish(starting_topic, starting_info, options=PublishOptions(exclude=[details.caller])) try: self._manhole_service.port = yield create_listening_port_from_config( config['endpoint'], factory, self.cbdir, reactor) except Exception as e: self._manhole_service = None emsg = "ERROR: manhole service endpoint cannot listen - {}".format( e) log.msg(emsg) raise ApplicationError("crossbar.error.cannot_listen", emsg) # alright, manhole has started self._manhole_service.started = datetime.utcnow() self._manhole_service.status = 'started' started_topic = '{}.on_manhole_started'.format(self._uri_prefix) started_info = self._manhole_service.marshal() self.publish(started_topic, started_info, options=PublishOptions(exclude=[details.caller])) returnValue(started_info)
def start_manhole(self, config, details=None): """ Start a Manhole service within this process. **Usage:** This procedure is registered under * ``crossbar.node.<node_id>.worker.<worker_id>.start_manhole`` - for native workers * ``crossbar.node.<node_id>.controller.start_manhole`` - for node controllers The procedure takes a Manhole service configuration which defines a listening endpoint for the service and a list of users including passwords, e.g. .. code-block:: javascript { "endpoint": { "type": "tcp", "port": 6022 }, "users": [ { "user": "******", "password": "******" } ] } **Errors:** The procedure may raise the following errors: * ``crossbar.error.invalid_configuration`` - the provided configuration is invalid * ``crossbar.error.already_started`` - the Manhole service is already running (or starting) * ``crossbar.error.feature_unavailable`` - the required support packages are not installed **Events:** The procedure will publish an event when the service **is starting** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_starting`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_starting`` - for node controllers and publish an event when the service **has started** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_started`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_started`` - for node controllers :param config: Manhole service configuration. :type config: dict """ self.log.debug("{cls}.start_manhole(config = {config})", cls=self.__class__.__name__, config=config) if not _HAS_MANHOLE: emsg = "Could not start manhole: required packages are missing ({})".format(_MANHOLE_MISSING_REASON) self.log.error(emsg) raise ApplicationError(u"crossbar.error.feature_unavailable", emsg) if self._manhole_service: emsg = "Could not start manhole - already running (or starting)" self.log.warn(emsg) raise ApplicationError(u"crossbar.error.already_started", emsg) try: checkconfig.check_manhole(config) except Exception as e: emsg = "Could not start manhole: invalid configuration ({})".format(e) self.log.error(emsg) raise ApplicationError(u'crossbar.error.invalid_configuration', emsg) # setup user authentication # checker = checkers.InMemoryUsernamePasswordDatabaseDontUse() for user in config['users']: checker.addUser(user['user'], user['password']) # setup manhole namespace # namespace = {'session': self} class PatchedTerminalSession(TerminalSession): # get rid of # exceptions.AttributeError: TerminalSession instance has no attribute 'windowChanged' def windowChanged(self, winSize): pass rlm = TerminalRealm() rlm.sessionFactory = PatchedTerminalSession # monkey patch rlm.chainedProtocolFactory.protocolFactory = lambda _: ColoredManhole(namespace) ptl = portal.Portal(rlm, [checker]) factory = ConchFactory(ptl) factory.noisy = False self._manhole_service = ManholeService(config, details.caller) starting_topic = '{}.on_manhole_starting'.format(self._uri_prefix) starting_info = self._manhole_service.marshal() # the caller gets a progressive result .. if details.progress: details.progress(starting_info) # .. while all others get an event self.publish(starting_topic, starting_info, options=PublishOptions(exclude=details.caller)) try: self._manhole_service.port = yield create_listening_port_from_config(config['endpoint'], self.cbdir, factory, self._reactor, self.log) except Exception as e: self._manhole_service = None emsg = "Manhole service endpoint cannot listen: {}".format(e) self.log.error(emsg) raise ApplicationError(u"crossbar.error.cannot_listen", emsg) # alright, manhole has started self._manhole_service.started = datetime.utcnow() self._manhole_service.status = 'started' started_topic = '{}.on_manhole_started'.format(self._uri_prefix) started_info = self._manhole_service.marshal() self.publish(started_topic, started_info, options=PublishOptions(exclude=details.caller)) returnValue(started_info)
def start_manhole(self, config, details = None): """ Start a manhole (SSH) within this worker. :param config: Manhole configuration. :type config: obj """ if self.debug: log.msg("{}.start_manhole".format(self.__class__.__name__), config) if not _HAS_MANHOLE: emsg = "ERROR: could not start manhole - required packages are missing ({})".format(_MANHOLE_MISSING_REASON) log.msg(emsg) raise ApplicationError("crossbar.error.feature_unavailable", emsg) if self._manhole_service: emsg = "ERROR: could not start manhole - already running (or starting)" log.msg(emsg) raise ApplicationError("crossbar.error.already_started", emsg) try: checkconfig.check_manhole(config) except Exception as e: emsg = "ERROR: could not start manhole - invalid configuration ({})".format(e) log.msg(emsg) raise ApplicationError('crossbar.error.invalid_configuration', emsg) ## setup user authentication ## checker = checkers.InMemoryUsernamePasswordDatabaseDontUse() for user in config['users']: checker.addUser(user['user'], user['password']) ## setup manhole namespace ## namespace = {'session': self} class PatchedTerminalSession(TerminalSession): ## get rid of ## exceptions.AttributeError: TerminalSession instance has no attribute 'windowChanged' def windowChanged(self, winSize): pass rlm = TerminalRealm() rlm.sessionFactory = PatchedTerminalSession # monkey patch rlm.chainedProtocolFactory.protocolFactory = lambda _: ColoredManhole(namespace) ptl = portal.Portal(rlm, [checker]) factory = ConchFactory(ptl) factory.noisy = False self._manhole_service = ManholeService(config, details.authid) starting_topic = '{}.on_manhole_starting'.format(self._uri_prefix) starting_info = self._manhole_service.marshal() ## the caller gets a progressive result .. if details.progress: details.progress(starting_info) ## .. while all others get an event self.publish(starting_topic, starting_info, options = PublishOptions(exclude = [details.caller])) try: self._manhole_service.port = yield create_listening_port_from_config(config['endpoint'], factory, self.cbdir, reactor) except Exception as e: self._manhole_service = None emsg = "ERROR: manhole service endpoint cannot listen - {}".format(e) log.msg(emsg) raise ApplicationError("crossbar.error.cannot_listen", emsg) ## alright, manhole has started self._manhole_service.started = datetime.utcnow() self._manhole_service.status = 'started' started_topic = '{}.on_manhole_started'.format(self._uri_prefix) started_info = self._manhole_service.marshal() self.publish(started_topic, started_info, options = PublishOptions(exclude = [details.caller])) returnValue(started_info)