Beispiel #1
0
    def view_createContainer(self, user, tag, data={}):
        """ Create a new Container object.

            @param user:        User for which the container will be created.
            @type  user:        rce.core.user.User

            @param tag:         Tag which is used to identify the container
                                in subsequent requests.
            @type  tag:         str

            @param data:        Extra data used to configure the container.
            @type  data:        dict
        """
        try:
            validateName(tag)
        except IllegalName as e:
            raise InvalidRequest('Container tag is invalid: {0}'.format(e))

        if tag in user.containers or tag in user.robots:
            raise InvalidRequest('Tag is already used for a container '
                                 'or robot.')

        namespace, remote_container = user.realm.createContainer(user.userID,
                                                                 data)
        container = Container(namespace, remote_container)
        user.containers[tag] = container
        container.notifyOnDeath(user.containerDied)

        m = 'Container {0} successfully created.'.format(tag)
        d = DeferredList([namespace(), remote_container()],
                         fireOnOneErrback=True, consumeErrors=True)
        return d.addCallback(lambda _: m)
Beispiel #2
0
    def createContainer(self, data, userID):
        """ # TODO: Add doc
        """
        if not self._ips:
            raise InvalidRequest('No more free IP addresses in subnet.')

        ip = data.pop('groupIP', None)

        if ip:
            addr, nr = ip.rsplit('.', 1)
            nr = int(nr)

            if addr != self._NETWORK_ADDR:
                addr = '{0}.0'.format(self._NETWORK_ADDR)
                raise InvalidRequest(
                    "IP address '{0}' is not in network range "
                    "'{1}'".format(ip, addr))

            try:
                self._ips.remove(nr)
            except KeyError:
                raise InvalidRequest("IP address '{0}' is already in "
                                     'use.'.format(ip))
        else:
            ip = '{1}.{0}'.format(self._ips.pop(), self._NETWORK_ADDR)

        return Container(data, userID, self, ip)
Beispiel #3
0
    def view_addInterface(self, user, eTag, iTag, iType, clsName, addr=''):
        """ Add an interface to an endpoint, i.e. a ROS environment or a
            Robot object.

            @param user:        User for which the interface will be added.
            @type  user:        rce.core.user.User

            @param eTag:        Tag which is used to identify the endpoint to
                                which the interface should be added; either
                                a container tag or robot ID.
            @type  eTag:        str

            @param iTag:        Tag which is used to identify the interface in
                                subsequent requests.
            @type  iTag:        str

            @param iType:       Type of the interface. The type consists of a
                                prefix and a suffix.
                                 - Valid prefixes are:
                                     ServiceClient, ServiceProvider,
                                     Publisher, Subscriber
                                 - Valid suffixes are:
                                     Interface, Converter, Forwarder
            @type  iType:       str

            @param clsName:     Message type/Service type consisting of the
                                package and the name of the message/service,
                                i.e. 'std_msgs/Int32'.
            @type  clsName:     str

            @param addr:        ROS name/address which the interface should
                                use. Only necessary if the suffix of @param
                                iType is 'Interface'.
            @type  addr:        str
        """
        if iType.endswith('Converter') or iType.endswith('Forwarder'):
            try:
                user.robots[eTag].addInterface(iTag, iType, clsName)
            except KeyError:
                raise InvalidRequest('Can not add Interface, because Robot '
                                     '{0} does not exist.'.format(eTag))
        elif iType.endswith('Interface'):
            try:
                user.containers[eTag].addInterface(iTag, iType, clsName, addr)
            except KeyError:
                raise InvalidRequest('Can not add Interface, because '
                                     'Container {0} does not '
                                     'exist.'.format(eTag))
        else:
            raise InvalidRequest('Interface type is invalid (Unknown suffix).')
Beispiel #4
0
    def view_get_rosapi_connect_info(self, user, tag):
        """ Remote call to get ROSAPI request URL and key for a particular
            container.

            @param user:        User who owns the container for which the URL
                                is requested.
            @type  user:        rce.core.user.User

            @param tag:         Tag used to identify the container.
            @type  tag:         str

            @return:            URL which can be used to connect to the rosproxy
                                running inside the container as well as the key
                                necessary to use the rosproxy.
                                (type: (str, str))
            @rtype:             twisted.internet.defer.Deferred
        """
        try:
            container = user.containers[tag]
        except KeyError:
            raise InvalidRequest('Container {0} does not exist.'.format(tag))

        uid = uuid4().hex
        container._obj.registerConsole(user.userID, uid)
        d = container.getConnectInfo()
        d.addCallback(lambda addr: (addr, uid))
        return d
Beispiel #5
0
    def view_addParameter(self, user, cTag, name, value):
        """ Add a parameter to a ROS environment.

            @param user:        User for which the parameter will be added.
            @type  user:        rce.core.user.User

            @param cTag:        Tag which is used to identify the ROS
                                environment to which the parameter should be
                                added.
            @type  cTag:        str

            @param name:        Name of the parameter which should be added.
                                It is also used to identify the parameter in
                                subsequent requests.
            @type  name:        str

            @param value:       Value of the parameter which should be added.
                                String values can contain the directives
                                $(find PKG) or $(env VAR).
            @type  value:       str, int, float, bool, list
        """
        try:
            user.containers[cTag].addParameter(name, value)
        except KeyError:
            raise InvalidRequest('Can not add Parameter, because Container '
                                 '{0} does not exist.'.format(cTag))
Beispiel #6
0
    def registerRobot(self, robot, robotID):
        """ Create a new Robot Wrapper.

            # TODO: Add description of arguments

            @raise:             rce.core.error.InvalidRequest
        """
        try:
            validateName(robotID)
        except IllegalName as e:
            raise InvalidRequest('Robot ID is invalid: {0}'.format(e))

        if (robotID in self.robots or robotID in self.containers):
            raise InvalidRequest('ID is already used for a container '
                                 'or robot.')

        robot = Robot(robot)
        self.robots[robotID] = robot
        robot.notifyOnDeath(self.robotDied)
Beispiel #7
0
 def perspective_getUserView(self, console=True):
     """
     """
     if self._userID == 'admin' and not console:
         raise InvalidRequest('Administrator cannot login via robot')
     elif self._userID == 'admin':
         return AdminMonitorView()
     elif not console:
         return ControlView()
     else:
         return {'console': MonitorView(), 'robot': ControlView()}
Beispiel #8
0
    def view_addConnection(self, user, tagA, tagB):
        """ Create a connection between two interfaces.

            @param user:        User for which the connection will be created.
            @type  user:        rce.core.user.User

            @param tagX:        Tag which is used to identify the interface
                                which should be connected. It has to be of the
                                form:
                                    [endpoint tag]/[interface tag]
                                For example:
                                    testRobot/logPublisher
            @type  tagX:        str
        """
        eTagA, iTagA = tagA.split('/', 2)
        eTagB, iTagB = tagB.split('/', 2)

        ifA = user.getEndpoint(eTagA).getInterface(iTagA)
        ifB = user.getEndpoint(eTagB).getInterface(iTagB)

        if ifA.clsName != ifB.clsName:
            raise InvalidRequest('Can not connect two interfaces with '
                                 'different message/service type.')

        if not Types.connectable(ifA.iType, ifB.iType):
            raise InvalidRequest('Can not connect an interface of type {0} '
                                 'and an interface of type '
                                 '{1}.'.format(Types.decode(ifA.iType),
                                               Types.decode(ifB.iType)))

        key = int(md5(tagA).hexdigest(), 16) ^ int(md5(tagB).hexdigest(), 16)

        if key in user.connections:
            raise InvalidRequest('Can not add the same connection twice.')

        connection = user.realm.createConnection(ifA.obj, ifB.obj)
        user.connections[key] = connection
        connection.notifyOnDeath(user.connectionDied)
Beispiel #9
0
    def view_destroyContainer(self, user, tag):
        """ Destroy a Container object.

            @param user:        User for which the container will be destroyed.
            @type  user:        rce.core.user.User

            @param tag:         Tag which is used to identify the container
                                which should be destroyed.
            @type  tag:         str
        """
        try:
            container = user.containers.pop(tag)
        except KeyError:
            raise InvalidRequest('Can not destroy non existent container.')

        container.dontNotifyOnDeath(user.containerDied)
        container.destroy()
Beispiel #10
0
    def getEndpoint(self, tag):
        """ Get an endpoint of the user matching the given tag.

            @param tag:         Tag which is used to identify the endpoint which
                                should be returned.
            @type  tag:         str

            @return:            Endpoint which was requested.
            @rtype:             rce.core.network.Endpoint

            @raise:             rce.core.error.InvalidRequest
        """
        if tag in self.robots:
            return self.robots[tag]
        elif tag in self.containers:
            return self.containers[tag]
        else:
            raise InvalidRequest('Can not get a non existent endpoint '
                                 "'{0}'.".format(tag))
Beispiel #11
0
    def view_stats_machine(self, user, machineIP):
        """ Remote call to list stats of machine with given IP.

            @param user:        User who requested the stats.
            @type  user:        rce.core.user.User

            @param machineIP:   IP of machine for which the stats should be
                                listed.
            @type  machineIP:   str

            @return:            Stats of the machine.
            @rtype:             { str : int }
        """
        try:
            machine = (machine for machine in user.realm._balancer._machines
                       if machineIP == machine.IP).next()
            return {'active':machine.active, 'size':machine.size}
        except StopIteration:
            raise InvalidRequest('No such machine.')
Beispiel #12
0
    def view_removeParameter(self, user, cTag, name):
        """ Remove a parameter from a ROS environment.

            @param user:        User for which the parameter will be destroyed.
            @type  user:        rce.core.user.User

            @param cTag:        Tag which is used to identify the ROS
                                environment from which the parameter should be
                                removed.
            @type  cTag:        str

            @param name:        Name of the parameter which should be removed.
            @type  name:        str
        """
        try:
            user.containers[cTag].removeParameter(name)
        except KeyError:
            raise InvalidRequest('Can not remove Parameter, because Container '
                                 '{0} does not exist.'.format(cTag))
Beispiel #13
0
    def view_addNode(self, user, cTag, nTag, pkg, exe, args='', name='',
                     namespace=''):
        """ Add a node to a ROS environment.

            @param user:        User for which the node will be added.
            @type  user:        rce.core.user.User

            @param cTag:        Tag which is used to identify the ROS
                                environment to which the node should be added.
            @type  cTag:        str

            @param nTag:        Tag which is used to identify the node in
                                subsequent requests.
            @type  nTag:        str

            @param pkg:         Name of ROS package where the node can be
                                found.
            @type  pkg:         str

            @param exe:         Name of executable (node) which should be
                                launched.
            @type  exe:         str

            @param args:        Additional arguments which should be used for
                                the launch. Can contain the directives
                                $(find PKG) or $(env VAR). Other special
                                characters as '$' or ';' are not allowed.
            @type  args:        str

            @param name:        Name of the node under which the node should be
                                launched.
            @type  name:        str

            @param namespace:   Namespace in which the node should be started
                                in the environment.
            @type  namespace:   str
        """
        try:
            user.containers[cTag].addNode(nTag, pkg, exe, args, name, namespace)
        except KeyError:
            raise InvalidRequest('Can not add Node, because Container {0} '
                                 'does not exist.'.format(cTag))
Beispiel #14
0
    def view_machine_containers(self, user, machineIP):
        """ Remote call to list containers in a machine with given IP.

            @param user:        User who requested the container list.
            @type  user:        rce.core.user.User

            @param machineIP:   IP of machine for which the running containers
                                should be listed.
            @type  machineIP:   str

            @return:            List of running containers.
            @rtype:             # TODO: Depends on modification below.
        """
        # TODO: Can not return rce.master.container.Container instances need
        #       some conversion into string, tuple, or some other base type
        try:
            return (machine for machine in user.realm._balancer._machines
                    if machineIP == machine.IP).next()._containers
        except StopIteration:
            raise InvalidRequest('No such machine.')
Beispiel #15
0
    def view_removeNode(self, user, cTag, nTag):
        """ Remove a node from a ROS environment.

            @param user:        User for which the node will be destroyed.
            @type  user:        rce.core.user.User

            @param cTag:        Tag which is used to identify the ROS
                                environment from which the node should be
                                removed.
            @type  cTag:        str

            @param nTag:        Tag which is used to identify the ROS node
                                which should removed.
            @type  nTag:        str
        """
        try:
            user.containers[cTag].removeNode(nTag)
        except KeyError:
            raise InvalidRequest('Can not remove Node, because Container {0} '
                                 'does not exist.'.format(cTag))
Beispiel #16
0
    def view_removeConnection(self, user, tagA, tagB):
        """ Destroy a connection between two interfaces.

            @param user:        User for which the connection will be destroyed.
            @type  user:        rce.core.user.User

            @param tagX:        Tag which is used to identify the interface
                                which should be disconnected. It has to be of
                                the form:
                                    [endpoint tag]/[interface tag]
                                For example:
                                    testRobot/logPublisher
            @type  tagX:        str
        """
        key = int(md5(tagA).hexdigest(), 16) ^ int(md5(tagB).hexdigest(), 16)

        try:
            connection = user.connections.pop(key)
        except KeyError:
                raise InvalidRequest('Can not disconnect two unconnected '
                                     'interfaces.')

        connection.dontNotifyOnDeath(user.connectionDied)
        connection.destroy()