Exemple #1
0
class ForwardOutput(Output):

    implements(IOutput)

    def configure(self, section):
        self.forwardserver = section.getString('forwarding address', None)
        self.forwardport = section.getInt('forwarding port', None)
        self.retryinterval = section.getInt('retry interval', 10)
        self.forwardedevents = getStat("terane.output.%s.forwardedevents" % self.name, 0)
        self.stalerefs = getStat("terane.output.%s.stalerefs" % self.name, 0)
        
    def startService(self):
        Output.startService(self)
        self._client = None
        self._listener = None
        self._remote = None
        self._backoff = None
        self._reconnect()

    def _reconnect(self):
        try:
            if self._client:
                self._client.disconnect()
            self._client = PBClientFactory()
            if self._listener:
                self._listener.disconnect()
            self._listener = reactor.connectTCP(self.forwardserver, self.forwardport, self._client)
            self._remote = self._client.login(Anonymous())
            self._remote.addCallback(self._login)
            self._remote.addErrback(self._loginFailed)
        except Exception, e:
            logger.error("[output:%s] failed to connect to remote collector: %s" % (self.name,str(e)))
            logger.error("[output:%s] will retry to connect in %i seconds" % (self.name,self.retryinterval))
            self._backoff = reactor.callLater(self.retryinterval, self._reconnect)
Exemple #2
0
    def login(self, userID, robotID, password):
        """ Callback for Robot connection to login and authenticate.

            @param userID:      User ID under which the robot is logging in.
            @type  userID:      str

            @param robotID:     Unique ID of the robot in the namespace of the
                                user under which the robot is logging in.
            @type  robotID:     str

            @param password:    Hashed password as hex-encoded string which is
                                used to authenticate the user.
            @type  password:    str

            @return:            Representation of the connection to the robot
                                which is used in the Robot process.
                                (type: rce.robot.Connection)
            @rtype:             twisted.internet.defer.Deferred
        """
        conn = Connection(self, userID, robotID)

        factory = PBClientFactory()
        self._reactor.connectTCP(self._masterIP, self._masterPort, factory)

        d = factory.login(UsernamePassword(userID, password))
        d.addCallback(self._cbAuthenticated, conn)
        d.addCallback(self._cbConnected, conn)
        d.addCallback(lambda _: conn)
        return d
Exemple #3
0
def main(reactor, cred, masterIP, masterPort, commPort, uid):
    f = open('/opt/rce/data/env.log', 'w') # TODO: Hardcoded? Use os.getenv('HOME')?
    log.startLogging(f)

    rospy.init_node('RCE_Master')
    print 'connect to ', masterIP, masterPort

    factory = PBClientFactory()
    reactor.connectTCP(masterIP, masterPort, factory)

    client = EnvironmentClient(reactor, commPort)

    def terminate():
        reactor.callFromThread(client.terminate)
        reactor.callFromThread(reactor.stop)

    rospy.on_shutdown(terminate)

    def _err(reason):
        print(reason)
        terminate()

    d = factory.login(cred, (client, uid))
    d.addCallback(lambda ref: setattr(client, '_avatar', ref))
    d.addErrback(_err)

    reactor.run(installSignalHandlers=False)

    f.close()
Exemple #4
0
    def login(self, userID, robotID, password):
        """ Callback for Robot connection to login and authenticate.

            @param userID:      User ID under which the robot is logging in.
            @type  userID:      str

            @param robotID:     Unique ID of the robot in the namespace of the
                                user under which the robot is logging in.
            @type  robotID:     str

            @param password:    Hashed password as hex-encoded string which is
                                used to authenticate the user.
            @type  password:    str

            @return:            Representation of the connection to the robot
                                which is used in the Robot process.
                                (type: rce.robot.Connection)
            @rtype:             twisted.internet.defer.Deferred
        """
        conn = Connection(self, userID, robotID)

        factory = PBClientFactory()
        self._reactor.connectTCP(self._masterIP, self._masterPort, factory)

        d = factory.login(UsernamePassword(userID, password))
        d.addCallback(self._cbAuthenticated, conn)
        d.addCallback(self._cbConnected, conn)
        d.addCallback(lambda _: conn)
        return d
Exemple #5
0
def main(reactor, cred, masterIP, masterPort, commPort, uid):
    f = open('/opt/rce/data/env.log', 'w')  # TODO: Use os.getenv('HOME') ?
    log.startLogging(f)

    rospy.init_node('RCE_Master')
    print 'connect to ', masterIP, masterPort

    factory = PBClientFactory()
    reactor.connectTCP(masterIP, masterPort, factory)

    client = EnvironmentClient(reactor, commPort)

    def terminate():
        reactor.callFromThread(client.terminate)
        reactor.callFromThread(reactor.stop)

    rospy.on_shutdown(terminate)

    def _err(reason):
        print(reason)
        terminate()

    d = factory.login(cred, (client, uid))
    d.addCallback(client.registerAvatar)
    d.addCallback(client.createEnvironment)
    d.addErrback(_err)

    reactor.run(installSignalHandlers=False)

    f.close()
Exemple #6
0
def main(
    reactor,
    cred,
    masterIP,
    masterPort,
    masterPassword,
    infraPasswd,
    bridgeIF,
    internalIP,
    bridgeIP,
    envPort,
    rosproxyPort,
    rootfsDir,
    confDir,
    dataDir,
    pkgDir,
    ubuntuRel,
    rosRel,
    data,
):
    log.startLogging(sys.stdout)

    def _err(reason):
        print(reason)
        reactor.stop()

    factory = PBClientFactory()
    reactor.connectTCP(masterIP, masterPort, factory)

    client = ContainerClient(
        reactor,
        masterIP,
        masterPort,
        masterPassword,
        infraPasswd,
        bridgeIF,
        internalIP,
        bridgeIP,
        envPort,
        rosproxyPort,
        rootfsDir,
        confDir,
        dataDir,
        pkgDir,
        ubuntuRel,
        rosRel,
        data,
    )

    d = factory.login(cred, (client, data))
    d.addCallback(lambda ref: setattr(client, "_avatar", ref))
    d.addErrback(_err)

    reactor.addSystemEventTrigger("before", "shutdown", client.terminate)
    reactor.run()
Exemple #7
0
def main():
    """
    Connect to a PB server running on port 8800 on localhost and log in to
    it, both anonymously and using a username/password it will recognize.
    """
    startLogging(stdout)
    factory = PBClientFactory()
    reactor.connectTCP("localhost", 8800, factory)

    anonymousLogin = factory.login(Anonymous())
    anonymousLogin.addCallback(connected)
    anonymousLogin.addErrback(error, "Anonymous login failed")

    usernameLogin = factory.login(UsernamePassword("user1", "pass1"))
    usernameLogin.addCallback(connected)
    usernameLogin.addErrback(error, "Username/password login failed")

    bothDeferreds = gatherResults([anonymousLogin, usernameLogin])
    bothDeferreds.addCallback(finished)

    reactor.run()
def main():
    """
    Connect to a PB server running on port 8800 on localhost and log in to
    it, both anonymously and using a username/password it will recognize.
    """
    startLogging(stdout)
    factory = PBClientFactory()
    reactor.connectTCP("localhost", 8800, factory)

    anonymousLogin = factory.login(Anonymous())
    anonymousLogin.addCallback(connected)
    anonymousLogin.addErrback(error, "Anonymous login failed")

    usernameLogin = factory.login(UsernamePassword("user1", "pass1"))
    usernameLogin.addCallback(connected)
    usernameLogin.addErrback(error, "Username/password login failed")

    bothDeferreds = gatherResults([anonymousLogin, usernameLogin])
    bothDeferreds.addCallback(finished)

    reactor.run()
Exemple #9
0
def main(reactor, cred, masterIP, masterPort, internalIF, bridgeIF, envPort,
         rootfsDir, confDir, dataDir, srcDir, pkgDir, maxNr):
    log.startLogging(sys.stdout)
    
    def _err(reason):
        print(reason)
        reactor.stop()
    
    factory = PBClientFactory()
    reactor.connectTCP(masterIP, masterPort, factory)
    
    client = ContainerClient(reactor, masterIP, internalIF, bridgeIF, envPort,
                             rootfsDir, confDir, dataDir, srcDir, pkgDir)
    
    d = factory.login(cred, (client, maxNr))
    d.addCallback(lambda ref: setattr(client, '_avatar', ref))
    d.addErrback(_err)
    
    reactor.addSystemEventTrigger('before', 'shutdown', client.terminate)
    reactor.run()
Exemple #10
0
def main(reactor, cred, masterIP, masterPort, consolePort,
                extIP, extPort, commPort, pkgPath, customConverters):
    log.startLogging(sys.stdout)

    def _err(reason):
        print(reason)
        reactor.stop()

    factory = PBClientFactory()
    reactor.connectTCP(masterIP, masterPort, factory)

    rosPath = []
    for path in get_ros_paths() + [p for p, _ in pkgPath]:
        if path not in rosPath:
            rosPath.append(path)

    loader = Loader(rosPath)
    converter = Converter(loader)

    for customConverter in customConverters:
        # Get correct path/name of the converter
        module, className = customConverter.rsplit('.', 1)

        # Load the converter
        mod = __import__(module, fromlist=[className])
        converter.addCustomConverter(getattr(mod, className))

    client = RobotClient(reactor, masterIP, consolePort, commPort, extIP,
                         extPort, loader, converter)
    d = factory.login(cred, client)
    d.addCallback(lambda ref: setattr(client, '_avatar', ref))
    d.addErrback(_err)

    # portal = Portal(client, (client,))
    robot = CloudEngineWebSocketFactory(client,
                                        'ws://localhost:{0}'.format(extPort))
    listenWS(robot)

    reactor.addSystemEventTrigger('before', 'shutdown', client.terminate)
    reactor.run()
Exemple #11
0
def main(reactor, cred, masterIP, masterPort, consolePort, extIP, extPort,
         commPort, pkgPath, customConverters):
    log.startLogging(sys.stdout)

    def _err(reason):
        print(reason)
        reactor.stop()

    factory = PBClientFactory()
    reactor.connectTCP(masterIP, masterPort, factory)

    rosPath = []
    for path in get_ros_paths() + [p for p, _ in pkgPath]:
        if path not in rosPath:
            rosPath.append(path)

    loader = Loader(rosPath)
    converter = Converter(loader)

    for customConverter in customConverters:
        # Get correct path/name of the converter
        module, className = customConverter.rsplit('.', 1)

        # Load the converter
        mod = __import__(module, fromlist=[className])
        converter.addCustomConverter(getattr(mod, className))

    client = RobotClient(reactor, masterIP, consolePort, commPort, extIP,
                         extPort, loader, converter)
    d = factory.login(cred, client)
    d.addCallback(lambda ref: setattr(client, '_avatar', ref))
    d.addErrback(_err)

    # portal = Portal(client, (client,))
    robot = CloudEngineWebSocketFactory(client,
                                        'ws://localhost:{0}'.format(extPort))
    listenWS(robot)

    reactor.addSystemEventTrigger('before', 'shutdown', client.terminate)
    reactor.run()
Exemple #12
0
class ForwardOutput(Output):

    implements(IOutput)

    def configure(self, section):
        self.forwardserver = section.getString('forwarding address', None)
        self.forwardport = section.getInt('forwarding port', None)
        self.retryinterval = section.getInt('retry interval', 10)
        self.forwardedevents = getStat(
            "terane.output.%s.forwardedevents" % self.name, 0)
        self.stalerefs = getStat("terane.output.%s.stalerefs" % self.name, 0)

    def startService(self):
        Output.startService(self)
        self._client = None
        self._listener = None
        self._remote = None
        self._backoff = None
        self._reconnect()

    def _reconnect(self):
        try:
            if self._client:
                self._client.disconnect()
            self._client = PBClientFactory()
            if self._listener:
                self._listener.disconnect()
            self._listener = reactor.connectTCP(self.forwardserver,
                                                self.forwardport, self._client)
            self._remote = self._client.login(Anonymous())
            self._remote.addCallback(self._login)
            self._remote.addErrback(self._loginFailed)
        except Exception, e:
            logger.error(
                "[output:%s] failed to connect to remote collector: %s" %
                (self.name, str(e)))
            logger.error("[output:%s] will retry to connect in %i seconds" %
                         (self.name, self.retryinterval))
            self._backoff = reactor.callLater(self.retryinterval,
                                              self._reconnect)
Exemple #13
0
def main(reactor, cred, masterIP, masterPort, masterPassword, infraPasswd,
         bridgeIF, internalIP, bridgeIP, envPort, rosproxyPort, rootfsDir,
         confDir, dataDir, pkgDir, ubuntuRel, rosRel, data):
    log.startLogging(sys.stdout)

    def _err(reason):
        print(reason)
        reactor.stop()

    factory = PBClientFactory()
    reactor.connectTCP(masterIP, masterPort, factory)

    client = ContainerClient(reactor, masterIP, masterPort, masterPassword,
                             infraPasswd, bridgeIF, internalIP, bridgeIP,
                             envPort, rosproxyPort, rootfsDir, confDir,
                             dataDir, pkgDir, ubuntuRel, rosRel, data)

    d = factory.login(cred, (client, data))
    d.addCallback(lambda ref: setattr(client, '_avatar', ref))
    d.addErrback(_err)

    reactor.addSystemEventTrigger('before', 'shutdown', client.terminate)
    reactor.run()
Exemple #14
0
 def _login(self, credentials, client=None):
     log.debug("_login called")
     d = PBClientFactory.login(self, credentials, client)
     d.addCallback(self._gotPerspective)
     d.addErrback(self.gotPerspectiveFailed)
     return d
Exemple #15
0
class ConsoleClient(HistoricRecvLine):
    """ The class creates the terminal and manages connections with Master
        and ROSAPI servers on specific containers
    """
    def __init__(self, masterIP, consolePort):
        """ Initialize the ConsoleClient.

            @param masterIP:        The IP of the master server
            @type  masterIP:        string

            @param consolePort:     Port of the master server
            @type  consolePort:     int
        """
        self._user = None
        self._masterIP = masterIP
        self._console_port = consolePort
        self._mode = "Username"
        self._username = None
        self._password = None
        self._factory = None
        self._connected_rosapi_nodes = {}
        self._privilege = None

    def showPrompt(self):
        """ Show the prompt >>>
        """
        self.terminal.nextLine()
        self.terminal.write(self.ps[self.pn])

    def connectionMade(self):
        """ Create a PBClientFactory and connect to master when ConsoleClient
            connected to StandardIO. Prompt user for Username
        """
        HistoricRecvLine.connectionMade(self)
        self._factory = PBClientFactory()

        reactor.connectTCP(self._masterIP, self._console_port, self._factory) #@UndefinedVariable
        self.terminal.write("Username: "******""" Manage state/mode after connection. Code uses states to take
            credential input and then starts terminal input.

            @param line:    line typed on terminal
            @type  line:    string
        """
        def _cbError(why, msg):
            err(why, msg)
            reactor.stop() #@UndefinedVariable

        def _cbConnectionSuccess(view):
            self._user = view

            if isinstance(self._user, dict):
                self._privilege = 'console'
            else:
                self._privilege = 'admin'

            self.terminal.write('Connection to Master Established.')
            self.showPrompt()

        if self._mode == 'Username':
            self._mode = 'Password'
            self._username = line
            self.terminal.write('Password: '******'Password':
            self._mode = 'Terminal'
            self._password = line
            cred = UsernamePassword(self._username,
                                    sha256(self._password).hexdigest())
            d = self._factory.login(cred)
            d.addCallback(lambda p: p.callRemote("getUserView", True))
            d.addCallback(_cbConnectionSuccess)
            d.addErrback(_cbError, "Username/password login failed")
        else:
            self.parseInputLine(line)

    def parseInputLine(self, line):
        """ A function to route various commands entered via Console.

            @param line:    The text entered on the Console
            @type  line:    string
        """
        if line is not None and line is not '':
            func = getattr(self, 'cmd_' + line.split()[0].upper(), None)
            if func is not None:
                func(line.split()[1:])
            else:
                self.terminal.write('No such command')
        self.showPrompt()

    @_errorHandle
    def callToRosProxy(self, command, parameter):
        """ Function to handle call to ROSAPI Proxy Server.

            @param command:      The command to execute in ROS environment.
            @type  command:      string

            @param parameter:    A parameter for the command.
            @type  parameter:    string
        """
        def perform_action((url, key)):
            self._connected_rosapi_nodes[parameter] = (url, key)
            argList = [('userID', self._username), ('action', command),
                       ('key', key)]

            try:
                f = urlopen('{0}?{1}'.format(url, urlencode(argList)))
                response = json.loads(f.read())
                self.terminal.write(str(response['key']))
            except HTTPError as e:
                msg = e.read()
                if msg:
                    msg = ' - {0}'.format(msg)

                self.terminal.write('HTTP Error {0}: '
                                    '{1}{2}'.format(e.getcode(), e.msg, msg))

        try:
            url, key = self._connected_rosapi_nodes[parameter]
            perform_action((url, key))
        except KeyError:
            d = self._user['console'].callRemote('get_rosapi_connect_info',
                                                 parameter)
            d.addCallback(perform_action)
            d.addErrback(lambda err: self.terminal.write("Problem "
                                "in connection with master: "
                                "{0}".format(err)))

    @_errorHandle
    def callToUser(self, command, domain, *args):
        """ A wrapper function for call to remote user.

            @param command:    The command to be executed
            @type  command:    string
        """
        if domain == 'admin':
            self._user.callRemote(command, *args)
        else:
            self._user[domain].callRemote(command, *args)

    @_errorHandle
    def callToUserAndDisplay(self, command, domain, *args):
        """ A wrapper function around call to user and displaying the result

            @param command:    The command to be executed
            @type  command:    string
        """
        if domain == 'admin':
            d = self._user.callRemote(command, *args)
            d.addCallback(lambda result: self.terminal.write(str(result)))
        else:
            d = self._user[domain].callRemote(command, *args)
            d.addCallback(lambda result: self.terminal.write(str(result)))

    #Various commands follow
    def cmd_EXIT(self, line):
        """ Handler for exit command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        reactor.stop() #@UndefinedVariable

    def cmd_USER(self, line):
        """ Handler for user command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = UserOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if opts['username'] and opts['password']:
                    self.callToUser('add_user', 'admin', opts['username'],
                                    opts['password'])
            elif cmd == 'remove':
                if opts['username']:
                    self.callToUser('remove_user', 'admin', opts['username'])
            elif cmd == 'update':
                if opts['username'] and opts['password']:
                    self.callToUser('update_user', 'admin',
                                    opts['username'], opts['password'])
            elif cmd == 'passwd':
                if opts['new'] and opts['old']:
                    self.callToUser('update_user', 'console', opts['new'],
                                    opts['old'])
            elif config['list']:
                self.callToUserAndDisplay('list_users', 'admin')

    def cmd_CONTAINER(self, line):
        """ Handler for container command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = ContainerOptions(self.terminal)

        try:
            config.parseOptions(line)
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if config['start']:
                self.callToUser('createContainer', 'robot', config['start'])
            elif config['stop']:
                self.callToUser('destroyContainer', 'robot', config['stop'])
            elif config['services']:
                self.callToRosProxy('services', config['services'])
            elif config['topics']:
                self.callToRosProxy('topics', config['topics'])
            elif config['list']:
                self.callToUserAndDisplay('list_containers', 'console')
            elif config['username']:
                self.callToUserAndDisplay('list_containers_by_user', 'admin',
                                          config['username'])

    def cmd_NODE(self, line):
        """ Handler for node command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = NodeOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'start':
                if (opts['args'] and opts['ctag'] and opts['ntag']
                    and opts['pkg'] and opts['exe']):
                    self.callToUser('addNode', 'robot', opts['ctag'],
                                    opts['ntag'], opts['pkg'], opts['exe'],
                                    opts['args'])
                elif (opts['ctag'] and opts['ntag']  and opts['pkg']
                      and opts['exe']):
                    self.callToUser('addNode', 'robot', opts['ctag'],
                                    opts['ntag'], opts['pkg'], opts['exe'])
            elif cmd == 'stop':
                if opts['ctag'] and opts['ntag']:
                    self.callToUser('removeNode', 'robot', opts['ctag'],
                                    opts['ntag'])

    def cmd_PARAMETER(self, line):
        """ Handler for parameter command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = ParameterOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if opts['ctag'] and opts['name'] and opts['value']:
                    self.callToUser('addParameter', 'robot', opts['ctag'],
                                    opts['name'], opts['value'])
            elif cmd == 'remove':
                if opts['ctag'] and opts['name']:
                    self.callToUser('removeParameter', 'robot', opts['ctag'],
                                    opts['name'])

    def cmd_INTERFACE(self, line):
        """ Handler for interface command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = InterfaceOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if (opts['addr'] and opts['etag'] and opts['itag']
                    and opts['itype'] and opts['icls']):
                    self.callToUser('addInterface', 'robot', opts['etag'],
                                    opts['itag'], opts['itype'], opts['icls'],
                                    opts['addr'])
                elif (opts['etag'] and opts['itag'] and opts['itype'] and
                      opts['icls']):
                    self.callToUser('addInterface', 'robot', opts['etag'],
                                    opts['itag'], opts['itype'], opts['icls'])
            elif cmd == 'remove':
                if opts['etag'] and opts['itag']:
                    self.callToUser('removeInterface', 'robot', opts['etag'],
                                    opts['itag'])

    def cmd_CONNECTION(self, line):
        """ Handler for connection command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = ConnectionOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if opts['tag1'] and opts['tag2']:
                    self.callToUser('addConnection', 'robot', opts['tag1'],
                                    opts['tag2'])
            elif cmd == 'remove':
                if opts['tag1'] and opts['tag2']:
                    self.callToUser('removeConnection', 'robot', opts['tag1'],
                                    opts['tag2'])

    def cmd_ROBOT(self, line):
        """ Handler for robot command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = RobotOptions(self.terminal)
        try:
            config.parseOptions(line)
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if config['list']:
                self.callToUserAndDisplay('list_robots', 'console')
            elif config['username']:
                self.callToUserAndDisplay('list_robots_by_user', 'admin',
                                          config['username'])

    def cmd_MACHINE(self, line):
        """ Handler for machine command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = MachineOptions(self.terminal)
        try:
            config.parseOptions(line)
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if config['list']:
                self.callToUserAndDisplay('list_machines', 'admin')
            elif config['stats']:
                self.callToUserAndDisplay('stats_machine', 'admin',
                                          config['stats'])
            elif config['containers']:
                self.callToUserAndDisplay('machine_containers', 'admin',
                                          config['containers'])

    def cmd_HELP(self, line):
        """ Handler for help command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        configs = [UserOptions(self.terminal), ContainerOptions(self.terminal),
                   NodeOptions(self.terminal), ParameterOptions(self.terminal),
                   InterfaceOptions(self.terminal),
                   ConnectionOptions(self.terminal),
                   RobotOptions(self.terminal), MachineOptions(self.terminal)]

        for config in configs:
            self.terminal.nextLine()
            config.opt_help()
Exemple #16
0
 def _login(self, credentials, client=None):
     log.debug("_login called")
     d = PBClientFactory.login(self, credentials, client)
     d.addCallback(self._gotPerspective)
     d.addErrback(self.gotPerspectiveFailed)
     return d
Exemple #17
0
class ConsoleClient(HistoricRecvLine):
    """ The class creates the terminal and manages connections with Master
        and ROSAPI servers on specific containers
    """
    def __init__(self, masterIP, consolePort):
        """ Initialize the ConsoleClient.

            @param masterIP:        The IP of the master server
            @type  masterIP:        string

            @param consolePort:     Port of the master server
            @type  consolePort:     int
        """
        self._user = None
        self._masterIP = masterIP
        self._console_port = consolePort
        self._mode = "Username"
        self._username = None
        self._password = None
        self._factory = None
        self._connected_rosapi_nodes = {}
        self._privilege = None

    def showPrompt(self):
        """ Show the prompt >>>
        """
        self.terminal.nextLine()
        self.terminal.write(self.ps[self.pn])

    def connectionMade(self):
        """ Create a PBClientFactory and connect to master when ConsoleClient
            connected to StandardIO. Prompt user for Username
        """
        HistoricRecvLine.connectionMade(self)
        self._factory = PBClientFactory()

        reactor.connectTCP(self._masterIP, self._console_port, self._factory)  #@UndefinedVariable
        self.terminal.write("Username: "******""" Manage state/mode after connection. Code uses states to take
            credential input and then starts terminal input.

            @param line:    line typed on terminal
            @type  line:    string
        """
        def _cbError(why, msg):
            err(why, msg)
            reactor.stop()  #@UndefinedVariable

        def _cbConnectionSuccess(view):
            self._user = view

            if isinstance(self._user, dict):
                self._privilege = 'console'
            else:
                self._privilege = 'admin'

            self.terminal.write('Connection to Master Established.')
            self.showPrompt()

        if self._mode == 'Username':
            self._mode = 'Password'
            self._username = line
            self.terminal.write('Password: '******'Password':
            self._mode = 'Terminal'
            self._password = line
            cred = UsernamePassword(self._username,
                                    sha256(self._password).hexdigest())
            d = self._factory.login(cred)
            d.addCallback(lambda p: p.callRemote("getUserView", True))
            d.addCallback(_cbConnectionSuccess)
            d.addErrback(_cbError, "Username/password login failed")
        else:
            self.parseInputLine(line)

    def parseInputLine(self, line):
        """ A function to route various commands entered via Console.

            @param line:    The text entered on the Console
            @type  line:    string
        """
        if line is not None and line is not '':
            func = getattr(self, 'cmd_' + line.split()[0].upper(), None)
            if func is not None:
                func(line.split()[1:])
            else:
                self.terminal.write('No such command')
        self.showPrompt()

    @_errorHandle
    def callToRosProxy(self, command, parameter):
        """ Function to handle call to ROSAPI Proxy Server.

            @param command:      The command to execute in ROS environment.
            @type  command:      string

            @param parameter:    A parameter for the command.
            @type  parameter:    string
        """
        def perform_action((url, key)):
            self._connected_rosapi_nodes[parameter] = (url, key)
            argList = [('userID', self._username), ('action', command),
                       ('key', key)]

            try:
                f = urlopen('{0}?{1}'.format(url, urlencode(argList)))
                response = json.loads(f.read())
                self.terminal.write(str(response['key']))
            except HTTPError as e:
                msg = e.read()
                if msg:
                    msg = ' - {0}'.format(msg)

                self.terminal.write('HTTP Error {0}: '
                                    '{1}{2}'.format(e.getcode(), e.msg, msg))

        try:
            url, key = self._connected_rosapi_nodes[parameter]
            perform_action((url, key))
        except KeyError:
            d = self._user['console'].callRemote('get_rosapi_connect_info',
                                                 parameter)
            d.addCallback(perform_action)
            d.addErrback(lambda err: self.terminal.write("Problem "
                                "in connection with master: "
                                "{0}".format(err)))

    @_errorHandle
    def callToUser(self, command, domain, *args):
        """ A wrapper function for call to remote user.

            @param command:    The command to be executed
            @type  command:    string
        """
        if domain == 'admin':
            self._user.callRemote(command, *args)
        else:
            self._user[domain].callRemote(command, *args)

    @_errorHandle
    def callToUserAndDisplay(self, command, domain, *args):
        """ A wrapper function around call to user and displaying the result

            @param command:    The command to be executed
            @type  command:    string
        """
        if domain == 'admin':
            d = self._user.callRemote(command, *args)
            d.addCallback(lambda result: self.terminal.write(str(result)))
        else:
            d = self._user[domain].callRemote(command, *args)
            d.addCallback(lambda result: self.terminal.write(str(result)))

    # Various commands follow
    def cmd_EXIT(self, line):
        """ Handler for exit command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        reactor.stop()  # @UndefinedVariable

    def cmd_USER(self, line):
        """ Handler for user command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = UserOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if opts['username'] and opts['password']:
                    self.callToUser('add_user', 'admin', opts['username'],
                                    opts['password'])
            elif cmd == 'remove':
                if opts['username']:
                    self.callToUser('remove_user', 'admin', opts['username'])
            elif cmd == 'update':
                if opts['username'] and opts['password']:
                    self.callToUser('update_user', 'admin',
                                    opts['username'], opts['password'])
            elif cmd == 'passwd':
                if opts['new'] and opts['old']:
                    self.callToUser('update_user', 'console', opts['new'],
                                    opts['old'])
            elif config['list']:
                self.callToUserAndDisplay('list_users', 'admin')

    def cmd_CONTAINER(self, line):
        """ Handler for container command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = ContainerOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'start':
                if (opts['name']):
                    data = {}
                    if opts.get('group'):
                        data['group'] = opts['group']
                    if opts.get('groupIp'):
                        data['groupIp'] = opts['groupIp']
                    if opts.get('size'):
                        data['size'] = opts['size']
                    if opts.get('bandwidth'):
                        data['bandwidth'] = opts['bandwidth']
                    if opts.get('memory'):
                        data['memory'] = opts['memory']
                    if opts.get('specialopts'):
                        data['specialFeatures'] = opts['specialopts']
                    self.callToUser('createContainer', 'robot', opts['name'],
                                    data)

            elif config['stop']:
                self.callToUser('destroyContainer', 'robot', config['stop'])
            elif config['services']:
                self.callToRosProxy('services', config['services'])
            elif config['topics']:
                self.callToRosProxy('topics', config['topics'])
            elif config['list']:
                self.callToUserAndDisplay('list_containers', 'console')
            elif config['username']:
                self.callToUserAndDisplay('list_containers_by_user', 'admin',
                                          config['username'])

    def cmd_NODE(self, line):
        """ Handler for node command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = NodeOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'start':
                if (opts['args'] and opts['ctag'] and opts['ntag']
                    and opts['pkg'] and opts['exe']):
                    self.callToUser('addNode', 'robot', opts['ctag'],
                                    opts['ntag'], opts['pkg'], opts['exe'],
                                    opts['args'])
                elif (opts['ctag'] and opts['ntag']  and opts['pkg']
                      and opts['exe']):
                    self.callToUser('addNode', 'robot', opts['ctag'],
                                    opts['ntag'], opts['pkg'], opts['exe'])
            elif cmd == 'stop':
                if opts['ctag'] and opts['ntag']:
                    self.callToUser('removeNode', 'robot', opts['ctag'],
                                    opts['ntag'])

    def cmd_PARAMETER(self, line):
        """ Handler for parameter command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = ParameterOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if opts['ctag'] and opts['name'] and opts['value']:
                    self.callToUser('addParameter', 'robot', opts['ctag'],
                                    opts['name'], opts['value'])
            elif cmd == 'remove':
                if opts['ctag'] and opts['name']:
                    self.callToUser('removeParameter', 'robot', opts['ctag'],
                                    opts['name'])

    def cmd_INTERFACE(self, line):
        """ Handler for interface command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = InterfaceOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if (opts['addr'] and opts['etag'] and opts['itag']
                    and opts['itype'] and opts['icls']):
                    self.callToUser('addInterface', 'robot', opts['etag'],
                                    opts['itag'], opts['itype'], opts['icls'],
                                    opts['addr'])
                elif (opts['etag'] and opts['itag'] and opts['itype'] and
                      opts['icls']):
                    self.callToUser('addInterface', 'robot', opts['etag'],
                                    opts['itag'], opts['itype'], opts['icls'])
            elif cmd == 'remove':
                if opts['etag'] and opts['itag']:
                    self.callToUser('removeInterface', 'robot', opts['etag'],
                                    opts['itag'])

    def cmd_CONNECTION(self, line):
        """ Handler for connection command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = ConnectionOptions(self.terminal)

        try:
            config.parseOptions(line)
            cmd = config.subCommand
            opts = config.subOptions if hasattr(config, 'subOptions') else {}
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if cmd == 'add':
                if opts['tag1'] and opts['tag2']:
                    self.callToUser('addConnection', 'robot', opts['tag1'],
                                    opts['tag2'])
            elif cmd == 'remove':
                if opts['tag1'] and opts['tag2']:
                    self.callToUser('removeConnection', 'robot', opts['tag1'],
                                    opts['tag2'])

    def cmd_ROBOT(self, line):
        """ Handler for robot command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = RobotOptions(self.terminal)
        try:
            config.parseOptions(line)
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if config['list']:
                self.callToUserAndDisplay('list_robots', 'console')
            elif config['username']:
                self.callToUserAndDisplay('list_robots_by_user', 'admin',
                                          config['username'])

    def cmd_MACHINE(self, line):
        """ Handler for machine command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        config = MachineOptions(self.terminal)
        try:
            config.parseOptions(line)
        except usage.UsageError as errortext:
            self.terminal.write("BUG in usage: {0}".format(errortext))
        else:
            if config['list']:
                self.callToUserAndDisplay('list_machines', 'admin')
            elif config['stats']:
                self.callToUserAndDisplay('stats_machine', 'admin',
                                          config['stats'])
            elif config['containers']:
                self.callToUserAndDisplay('machine_containers', 'admin',
                                          config['containers'])

    def cmd_HELP(self, line):
        """ Handler for help command.

            @param line:    line input from terminal.
            @type  line:    string
        """
        configs = [UserOptions(self.terminal), ContainerOptions(self.terminal),
                   NodeOptions(self.terminal), ParameterOptions(self.terminal),
                   InterfaceOptions(self.terminal),
                   ConnectionOptions(self.terminal),
                   RobotOptions(self.terminal), MachineOptions(self.terminal)]

        for config in configs:
            self.terminal.nextLine()
            config.opt_help()