Пример #1
0
    def _getEndpointConnection(self, epA, epB):
        """ Internally used method to get the connection between two endpoints.

            @param epX:         The endpoint which is part of the connection
                                that should be retrieved.
            @type  epX:         rce.core.network.Endpoint

            @return:            Connection between the two endpoints.
            @rtype:             rce.core.network.EndpointConnection
        """
        if epA not in self._endpoints or epB not in self._endpoints:
            raise InternalError('Endpoint is not part of this network.')

        if epA == epB:
            return epA.getLoopback()
        else:
            connectionsA = self._endpoints[epA]
            connectionsB = self._endpoints[epB]

            candidates = connectionsA.intersection(connectionsB)

            if candidates:
                if len(candidates) != 1:
                    raise InternalError('There are more than one possible '
                                        'endpoint connections.')

                return candidates.pop()
            else:
                connection = EndpointConnection(epA, epB)
                connectionsA.add(connection)
                connectionsB.add(connection)
                return connection
Пример #2
0
    def remote_createTunnel(self, name, targetIP):
        """ Create a new GRE Tunnel.

            @param name:        Unique name of the network group.
            @type  name:        str

            @param targetIP:    Target IP for the GRE Tunnel.
            @type  targetIP:    str

            @return:            Exit status of command.
            @rtype:             twisted.internet.defer.Deferred
        """
        if name not in self._bridges:
            raise InternalError('Bridge does not exist.')

        key = (name, targetIP)

        if key in self._uid:
            raise InternalError('Tunnel already exists.')

        while 1:
            uid = randomString(self._UID_LEN)

            if uid not in self._uid.itervalues():
                break

        self._uid[key] = uid
        port = 'gre-{0}'.format(uid)

        return execute(
            ('/usr/bin/ovs-vsctl', 'add-port', 'br-{0}'.format(name), port,
             '--', 'set', 'interface', port, 'type=gre',
             'options:remote_ip={0}'.format(targetIP)),
            reactor=self._reactor)
Пример #3
0
    def send(self, msg, msgID, protocol, remoteID):
        """ This method is used to send a message to the endpoint.

            Don't overwrite this method; instead overwrite the method _send.
            If the interface does not overwrite the method _send, it is assumed
            that the interface does not support this action and an
            InternalError is raised when send is called.

            @param msg:         Message which should be sent in serialized
                                form.
            @type  msg:         str

            @param msgID:       Message ID which is used to match response
                                message.
            @type  msgID:       str

            @param protocol:    Protocol instance through which the message
                                was sent.
            @type  protocol:    rce.slave.protocol._Protocol

            @param remoteID:    Unique ID of the Interface which sent the
                                message.
            @type  remoteID:    uuid.UUID
        """
        if not self._ready:
            raise InternalError('Interface is not ready to send a message.')

        try:
            if remoteID not in self._protocols[protocol]:
                raise KeyError
        except KeyError:
            log.msg('Received message dropped, because interface does not '
                    'expected the message.')

        self._send(msg, msgID, protocol, remoteID)
Пример #4
0
    def _send(self, msg, msgID, protocol, remoteID):
        """ Convert a ROS message into a JSON encoded message.

            @param msg:         Received ROS message in serialized form.
            @type  msg:         str

            @param msgID:       Unique ID to identify the message.
            @type  msgID:       str

            @param protocol:    Protocol instance through which the message
                                was sent.
            @type  protocol:    rce.slave.protocol._Protocol

            @param remoteID:    Unique ID of the Interface which sent the
                                message.
            @type  remoteID:    uuid.UUID
        """
        if not self._outputMsgCls:
            raise InternalError('This converter can not handle outgoing '
                                'messages.')

        rosMsg = self._outputMsgCls()
        rosMsg.deserialize(msg)

        try:
            jsonMsg = self._converter.encode(rosMsg)
        except (TypeError, ValueError) as e:
            raise ConversionError(str(e))

        self._sendToClient(jsonMsg, msgID, protocol, remoteID)
Пример #5
0
    def requestAvatar(self, avatarId, mind, *interfaces):
        """ Returns Avatar for slave processes of the cloud engine.

            Implementation for IRealm
        """
        if IPerspective not in interfaces:
            raise NotImplementedError('RoboEarthCloudEngine only '
                                      'handles IPerspective.')

        # There are three possible roles (=avatarId):
        #     'container', 'robot', and 'environment'
        if avatarId == 'container':
            machine = self._balancer.createMachine(mind[0], mind[1])
            avatar = MachineAvatar(machine, self._balancer)
            detach = lambda: avatar.logout()
            print('Connection to Container process established.')
        elif avatarId == 'robot':
            endpoint = RobotEndpoint(self._network, self._distributor,
                                     self._port)
            endpoint.callback(mind)
            avatar = RobotEndpointAvatar(self, endpoint)
            detach = lambda: avatar.logout()
            print('Connection to Robot process established.')
        elif avatarId == 'environment':
            endpoint = self._pendingContainer.pop(mind[1])
            endpoint.callback(mind[0])
            avatar = EnvironmentEndpointAvatar(self, endpoint)
            detach = lambda: avatar.logout()
            print('Connection to Environment process established.')
        else:
            raise InternalError('Invalid avatar ID received.')

        return IPerspective, avatar, detach
Пример #6
0
    def remote_createInterface(self, uid, iType, msgType, addr):
        """ Create an Interface object in the namespace and therefore in
            the endpoint.

            @param uid:         Unique ID which is used to identify the
                                interface in the internal communication.
            @type  uid:         str

            @param iType:       Type of the interface encoded as an integer.
                                Refer to rce.slave.interface.Types for more
                                information.
            @type  IType:       int

            @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:        Unique address which is used to identify the
                                interface in the external communication.
            @type  addr:        str

            @return:            New Interface instance.
            @rtype:             rce.slave.interface.Interface
        """
        try:
            cls = self._map[iType]
        except KeyError:
            raise InternalError('Interface type is not supported by this '
                                'namespace.')

        return cls(self, UUID(bytes=uid), msgType, addr)
Пример #7
0
    def createContainer(self, userID, data):
        """ Callback for User instance to create a new Container object in a
            container process.

            @param userID:      UserID of the user who created the container.
            @type  userID:      str

            @param data:        Extra data which is used to configure the
                                container.
            @param data:        dict

            @return:            New Namespace and Container instance.
            @rtype:             (rce.core.environment.Environment,
                                 rce.core.container.Container)
                                 (subclasses of rce.core.base.Proxy)
        """
        while 1:
            uid = uuid4().hex

            if uid not in self._pendingContainer:
                break

        try:
            container = self._balancer.createContainer(uid, userID, data)
        except ContainerProcessError:
            # TODO: What should we do here?
            raise InternalError('Container can not be created.')

        endpoint = EnvironmentEndpoint(self._network, container)
        self._pendingContainer[uid] = endpoint
        return endpoint.createNamespace(), container
Пример #8
0
    def receive(self, clsName, msgID, msg):
        """ Convert a JSON encoded message into a ROS message.

            @param clsName:     Message/Service type of the received message.
            @type  clsName:     str

            @param msgID:       Identifier which is used to match request /
                                response message.
            @type  msgID:       str

            @param msg:         JSON compatible message which should be
                                processed.
            @type  msg:         dict
        """
        if not self._inputMsgCls:
            raise InternalError('This converter can not handle incoming'
                                ' messages.')

        if clsName != self._clsName:
            raise InvalidResoureName('Sent message type does not match the '
                                     'used message type for this interface.')

        try:
            msg = self._converter.decode(self._inputMsgCls, msg)
        except (TypeError, ValueError) as e:
            raise ConversionError(str(e))

        buf = StringIO()
        msg.serialize(buf)
        msg = buf.getvalue()

        self._receive(msg, msgID)
Пример #9
0
    def returnNr(self, nr):
        """ Callback for Container to return a container number when it is
            no longer in use such that it can be reused.
        """
        if nr in self._nrs:
            raise InternalError('Number was never rented out.')

        self._nrs.add(nr)
Пример #10
0
    def createEnvironment(self, _):
        """ Create the Environment namespace.
        """
        if self._namespaces:
            raise InternalError('The environment can have only one namespace '
                                'at a time.')

        environment = Environment(self)
        return self._avatar.callRemote('setupNamespace', environment)
Пример #11
0
    def registerIAASHook(self, hook):
        """ Register an IAAS Hook object.

             # TODO: Add doc
        """
        if not isinstance(hook, IaasHook):
            raise InternalError('IAAS hook has to be a subclass of '
                                'rce.util.iaas.IaasHook.')

        self._iaas = hook
Пример #12
0
    def assignMachine(self, machine):
        """ # TODO: Add doc
        """
        if self._machine:
            raise InternalError('Can not assign the same container multiple '
                                'times.')

        self._machine = machine

        self._group.registerContainer(self)
        machine.registerContainer(self)
Пример #13
0
    def destroyMachine(self, machine):
        """ Destroy a Machine object.

            @param machine:     Machine instance which should be destroyed.
            @type  machine:     rce.core.machine.Machine
        """
        try:
            self._machines.remove(machine)
        except KeyError:
            raise InternalError('Tried to remove a non existent machine.')

        machine.destroy()
Пример #14
0
    def createNamespace(self):
        """ Create a Environment object in the environment endpoint.

            @return:            New Environment instance.
            @rtype:             rce.master.environment.Environment
                                (subclass of rce.core.base.Proxy)
        """
        if self._namespaces:
            raise InternalError('Can not have more than one namespace '
                                'in an Environment endpoint at a time.')

        return Environment(self)
Пример #15
0
    def addCustomConverter(self, converter):
        """ Register a new custom Converter.

            @raise:     rce.error.InternalError,
                        rce.util.interfaces.InterfaceError
        """
        verifyClass(ICustomROSConverter, converter)

        if converter.MESSAGE_TYPE in self._customTypes:
            raise InternalError('There are multiple Converters given for '
                                'message type "{0}".'.format(
                                    converter.MESSAGE_TYPE))

        try:
            pkg, name = package_resource_name(converter.MESSAGE_TYPE)
        except ValueError:
            raise InternalError('msg type is not valid. Has to be of the from '
                                'pkg/msg, i.e. std_msgs/Int8.')

        self._customTypes[converter.MESSAGE_TYPE] = (converter,
            self._loader.loadMsg(pkg, name))
Пример #16
0
    def removeCustomConverter(self, msgType):
        """ Unregister a custom Converter.

            @param msgType:     Message type of ROS message as a string, i.e.
                                'std_msgs/Int8', for which the converter should
                                be removed.
            @type  msgType:     str
        """
        try:
            del self._customTypes[msgType]
        except KeyError:
            InternalError('Tried to remove a custom converter which was '
                          'never added.')
Пример #17
0
    def getInterfaceConnection(self, interface, protocol):
        """ Get the connection between an interface and a protocol.

            @param interface:   Interface which belongs to this endpoint and
                                which is on one side of the connection.
            @type  interface:   rce.core.network.Interface

            @param protocol:    Protocol which belongs to this endpoint and
                                which is on one side of the connection.
            @type  protocol:    rce.core.network.Protocol

            @return:            Connection between the interface and the
                                protocol.
            @rtype:             rce.core.network.InterfaceConnection
        """
        try:
            connectionI = self._interfaces[interface]
        except KeyError:
            raise InternalError('Interface does not belong to this endpoint.')

        try:
            connectionP = self._protocols[protocol]
        except KeyError:
            raise InternalError('Protocol does not belong to this endpoint.')

        candidates = connectionP.intersection(connectionI)

        if candidates:
            if len(candidates) != 1:
                raise InternalError('There are more than one possible '
                                    'interface-protocol connections.')

            return candidates.pop()
        else:
            connection = InterfaceConnection(interface, protocol)
            connectionI.add(connection)
            connectionP.add(connection)
            return connection
Пример #18
0
    def remote_destroyTunnel(self, name, targetIP):
        """ Destroy a GRE Tunnel.

            @param name:        Unique name of the network group.
            @type  name:        str

            @param targetIP:    Target IP for the GRE Tunnel.
            @type  targetIP:    str

            @return:            Exit status of command.
            @rtype:             twisted.internet.defer.Deferred
        """
        if name not in self._bridges:
            raise InternalError('Bridge does not exist.')

        key = (name, targetIP)

        if key not in self._uid:
            raise InternalError('Tunnel deos not exist.')

        return execute(('/usr/bin/ovs-vsctl', 'del-port', 'gre-{0}'.format(
            self._uid.pop(key))),
                       reactor=self._reactor)
Пример #19
0
    def remote_destroyBridge(self, name):
        """ Destroy a OVS Bridge.

            @param name:        Unique name of the network group.
            @type  name:        str

            @return:            Exit status of command.
            @rtype:             twisted.internet.defer.Deferred
        """
        if name not in self._bridges:
            raise InternalError('Bridge does not exist.')

        self._bridges.remove(name)
        return execute(('/usr/bin/ovs-vsctl', 'del-br', 'br-{0}'.format(name)),
                       reactor=self._reactor)
Пример #20
0
    def remote_createBridge(self, name):
        """ Create a new OVS Bridge.

            @param name:        Unique name of the network group.
            @type  name:        str

            @return:            Exit status of command.
            @rtype:             twisted.internet.defer.Deferred
        """
        if name in self._bridges:
            raise InternalError('Bridge already exists.')

        self._bridges.add(name)
        return execute(('/usr/bin/ovs-vsctl', '--', '--may-exist', 'add-br',
                        'br-{0}'.format(name)),
                       reactor=self._reactor)
Пример #21
0
    def _validate(self, result):
        """ Internally used method which is part of a callback chain.
            Its task is to verify that both sides of the connection could be
            authenticated. In case both signal success the corresponding
            protocols are registered.
        """
        ((serverAuth, clientProtocol), (clientAuth, serverProtocol)) = result

        if not (serverAuth and clientAuth):
            # There was a problem in authenticating the connection
            # TODO: What should we do here?
            return Failure(
                InternalError('Connection could not be '
                              'authenticated.'))

        self._serverProtocol.callback(serverProtocol)
        self._clientProtocol.callback(clientProtocol)
Пример #22
0
    def sendMessage(self, interface, msg, msgID, remoteID=None):
        assert self._initialized

        uid = interface.UID.bytes
        assert len(uid) == 16

        try:
            idLen = self._MSG_ID_STRUCT.pack(len(msgID))
        except struct.error:
            raise InternalError('Message ID is too long.')

        if remoteID:
            flag = self._TRUE
            rmtID = remoteID.bytes
            assert len(rmtID) == 16
        else:
            flag = self._FALSE
            rmtID = ''

        self.sendString(''.join((flag, rmtID, uid, idLen, msgID, msg)))
Пример #23
0
    def requestURL(self, userID):
        """ Callback for Robot resource to retrieve the location of the Robot
            process to which a WebSocket connection should be established.

            @param userID:      User ID under which the robot will login.
                                (Can be used to do optimizations in distributing
                                the load.)
            @type  userID:      str

            @return:            The IP address of Robot process to which a
                                WebSocket connection should be established.
                                (type: str)
            @rtype:             twisted.internet.defer.Deferred
        """
        try:
            location = self._distributor.getNextLocation()
        except RobotProcessError:
            # TODO: What should we do here?
            raise InternalError('Robot can not be created.')

        return location.getWebsocketAddress()
Пример #24
0
    def createMachine(self, ref, data):
        """ Create a new Machine object, which can be used to create new
            containers.

            @param ref:         Remote reference to the ContainerClient in the
                                container process.
            @type  ref:         twisted.spread.pb.RemoteReference

            @param data:        Data about the machine
            @type  data:        dict

            @return:            New Machine instance.
            @rtype:             rce.core.machine.Machine
        """
        machine = Machine(ref, data, self)

        if machine in self._machines:
            raise InternalError(
                'Tried to add the same machine multiple times.')

        self._machines.add(machine)
        return machine
Пример #25
0
    def getProtocol(self, endpoint):
        """ Get the protocol which is part of this connection and belongs to
            the given endpoint.

            @param endpoint:    Endpoint to which the protocol has to belong.
            @type  endpoint:    rce.core.network.Endpoint

            @return:            Protocol which belongs to the endpoint and is
                                part of this connection.
            @rtype:             rce.core.network.Protocol
                                (subclass of rce.core.base.Proxy)
        """
        if not (self._serverProtocol and self._serverEndpoint
                and self._clientProtocol and self._clientEndpoint):
            raise ConnectionError('Endpoint connection is dead.')

        if self._serverEndpoint == endpoint:
            return self._serverProtocol
        elif self._clientEndpoint == endpoint:
            return self._clientProtocol
        else:
            raise InternalError('The endpoint is not part of this connection.')
Пример #26
0
    def _getAddress(self, result):
        """ Internally used method which is part of a callback chain.
            Its task is to verify that both endpoints are ready for the
            connection attempt. In case both signal readiness the address
            of the designated server endpoint is retrieved.

            @param result:      Response of the DeferredList containing the
                                Deferreds of the 'prepareConnection' calls.

            @return:            Address of the endpoint's internal
                                communication server.
            @rtype:             twisted.internet.address.IPv4Address
        """
        ((serverReady, _), (clientReady, _)) = result

        if not (serverReady and clientReady):
            # There was a problem in making the server/client ready for the
            # connection attempt
            # TODO: What should we do here?
            return Failure(
                InternalError('Server/Client could not be prepared '
                              'for connection attempt.'))

        return self._serverEndpoint.getAddress()
Пример #27
0
 def _send(self, msg, msgID, protocol, remoteID):
     raise InternalError('Interface does not support sending of a message.')
Пример #28
0
    def remote_connect(self, protocol, remoteID):
        if self._protocols:
            raise InternalError('Can not register more than one interface '
                                'at a time with a Service-Provider.')

        return _ROSInterfaceBase.remote_connect(self, protocol, remoteID)