Пример #1
0
    def _deserialize_properties(props):
        """
        Converts properties values into their type
        """
        new_props = {}
        for key, value in props.items():
            key = to_str(key)

            if is_bytes(value):
                # Convert value to string if necessary
                value = to_str(value)

            try:
                try:
                    new_props[key] = json.loads(value)
                except (TypeError, ValueError):
                    if is_string(value) and value.startswith("pelix-type:"):
                        # Pseudo-serialized
                        value_type, value = value.split(":", 3)[2:]
                        if "." in value_type and value_type not in value:
                            # Not a builtin type...
                            _logger.warning(
                                "Won't work: %s (%s)", value, value_type
                            )

                        new_props[key] = eval(value)
                    else:
                        # String
                        new_props[key] = value
            except Exception as ex:
                _logger.error("Can't deserialize %s: %s", value, ex)

        return new_props
Пример #2
0
    def _deserialize_properties(props):
        """
        Converts properties values into their type
        """
        new_props = {}
        for key, value in props.items():
            key = to_str(key)

            if is_bytes(value):
                # Convert value to string if necessary
                value = to_str(value)

            try:
                try:
                    new_props[key] = json.loads(value)
                except (TypeError, ValueError):
                    if is_string(value) and value.startswith("pelix-type:"):
                        # Pseudo-serialized
                        value_type, value = value.split(":", 3)[2:]
                        if '.' in value_type and value_type not in value:
                            # Not a builtin type...
                            _logger.warning("Won't work: %s (%s)", value,
                                            value_type)

                        new_props[key] = eval(value)
                    else:
                        # String
                        new_props[key] = value
            except Exception as ex:
                _logger.error("Can't deserialize %s: %s", value, ex)

        return new_props
Пример #3
0
    def __prepare_message(self, message, parent_uid=None):
        """
        Prepares a HTTP request.

        :param message: The Message bean to send
        :param parent_uid: UID of the message this one replies to (optional)
        :return: A (headers, content) tuple
        """
        # Prepare headers
        headers = {'content-type': CONTENT_TYPE_JSON,
                   'herald-subject': message.subject,
                   'herald-uid': message.uid,
                   'herald-sender-uid': self.__peer_uid,
                   'herald-timestamp': int(time.time() * 1000),
                   'herald-port': self.__access_port,
                   'herald-path': self.__access_path}
        if parent_uid:
            headers['herald-reply-to'] = parent_uid

        if message.subject in herald.SUBJECTS_RAW:
            content = to_str(message.content)
        else:
            # Convert content to JSON
            jabsorb_content = jabsorb.to_jabsorb(message.content)
            content = json.dumps(jabsorb_content, default=utils.json_converter)
        return headers, content
Пример #4
0
    def __on_message(self, client, msg):
        """
        An MQTT message has been received

        :param client: MQTT client
        :param msg: A MQTTMessage bean
        """
        try:
            # Parse the message
            data = json.loads(to_str(msg.payload))

        except ValueError as ex:
            # Bad content
            _logger.error("Error reading MQTT-RPC request: %s", ex)
            return

        try:
            if data[KEY_SENDER] == self._framework_uid:
                # We published this message
                return
        except KeyError:
            # Not sent by us
            pass

        # Handle the request in a different thread
        threading.Thread(name="MQTT-RPC-Exporter",
                         target=self.__handle_rpc, args=(data,)).start()
Пример #5
0
    def do_POST(self, request, response):
        """
        Handles a POST request

        :param request: Request handler
        :param response: Response handler
        """
        # Split the path
        path_parts = request.get_path().split('/')

        if path_parts[-1] != "endpoints":
            # Bad path
            response.send_content(404, "Unhandled path", "text/plain")
            return

        # Read the content
        endpoints = json.loads(to_str(request.read_data()))

        if endpoints:
            # Got something
            sender = request.get_client_address()[0]
            for endpoint in endpoints:
                self._registry.add(self._make_endpoint_bean(endpoint, sender))

        # We got the end points
        response.send_content(200, 'OK', 'text/plain')
Пример #6
0
    def do_POST(self, request, response):
        """
        Handles a POST request

        :param request: Request handler
        :param response: Response handler
        """
        # Split the path
        path_parts = request.get_path().split('/')

        if path_parts[-1] != "endpoints":
            # Bad path
            response.send_content(404, "Unhandled path", "text/plain")
            return

        # Read the content
        endpoints = json.loads(to_str(request.read_data()))

        if endpoints:
            # Got something
            sender = request.get_client_address()[0]
            for endpoint in endpoints:
                self._registry.add(self._make_endpoint_bean(endpoint, sender))

        # We got the end points
        response.send_content(200, 'OK', 'text/plain')
Пример #7
0
    def do_POST(self, request, response):
        """
        Handle a POST request

        :param request: The HTTP request bean
        :param request: The HTTP response handler
        """
        # Get the request JSON content
        data = jsonrpclib.loads(to_str(request.read_data()))

        # Convert from Jabsorb
        data = jabsorb.from_jabsorb(data)

        # Dispatch
        try:
            result = self._unmarshaled_dispatch(data, self._simple_dispatch)
        except NoMulticallResult:
            # No result (never happens, but who knows...)
            result = None

        if result is not None:
            # Convert result to Jabsorb
            if 'result' in result:
                result['result'] = jabsorb.to_jabsorb(result['result'])

            # Store JSON
            result = jsonrpclib.jdumps(result)
        else:
            # It was a notification
            result = ''

        # Send the result
        response.send_content(200, result, 'application/json-rpc')
Пример #8
0
    def __grab_data(host, port, path):
        """
        Sends a HTTP request to the server at (host, port), on the given path.
        Returns the parsed response.
        Returns None if the HTTP result is not 200 or in case of error.

        :param host: Dispatcher host address
        :param port: Dispatcher HTTP service port
        :param path: Request path
        :return: The parsed response content, or None
        """
        # Request the end points
        try:
            conn = httplib.HTTPConnection(host, port)
            conn.request("GET", path)
            result = conn.getresponse()
            data = result.read()
            conn.close()
        except Exception as ex:
            _logger.error("Error accessing the dispatcher servlet: %s", ex)
            return

        if result.status != 200:
            # Not a valid result
            return

        try:
            # Convert the response to a string
            data = to_str(data)
            # Parse the JSON result
            return json.loads(data)
        except ValueError as ex:
            # Error parsing data
            _logger.error("Error reading the response of the dispatcher: %s",
                          ex)
Пример #9
0
    def __send_message(self, msgtype, target, message, parent_uid=None):
        """
        Prepares and sends a message over XMPP

        :param msgtype: Kind of message (chat or groupchat)
        :param target: Target JID or MUC room
        :param message: Herald message bean
        :param parent_uid: UID of the message this one replies to (optional)
        """
        # Convert content to JSON
        if message.subject in herald.SUBJECTS_RAW:
            content = to_str(message.content)
        else:
            content = json.dumps(jabsorb.to_jabsorb(message.content),
                                 default=utils.json_converter)

        # Prepare an XMPP message, based on the Herald message
        xmpp_msg = self._bot.make_message(mto=target,
                                          mbody=content,
                                          msubject=message.subject,
                                          mtype=msgtype)
        xmpp_msg['thread'] = message.uid
        if parent_uid:
            xmpp_msg['parent_thread'] = parent_uid

        # Store message content
        self._probe.store(
            herald.PROBE_CHANNEL_MSG_CONTENT,
            {"uid": message.uid, "content": content}
        )

        # Send it, using the 1-thread pool, and wait for its execution
        future = self.__pool.enqueue(xmpp_msg.send)
        return future.result()
Пример #10
0
    def do_POST(self, request, response):
        """
        Handle a POST request

        :param request: The HTTP request bean
        :param request: The HTTP response handler
        """
        # Get the request JSON content
        data = jsonrpclib.loads(to_str(request.read_data()))

        # Convert from Jabsorb
        data = jabsorb.from_jabsorb(data)

        # Dispatch
        try:
            result = self._unmarshaled_dispatch(data, self._simple_dispatch)

        except NoMulticallResult:
            # No result (never happens, but who knows...)
            result = None

        if result is not None:
            # Convert result to Jabsorb
            if 'result' in result:
                result['result'] = jabsorb.to_jabsorb(result['result'])

            # Store JSON
            result = jsonrpclib.jdumps(result)

        else:
            # It was a notification
            result = ''

        # Send the result
        response.send_content(200, result, 'application/json-rpc')
Пример #11
0
    def handle_mqtt_message(self, mqtt_topic, payload):
        """
        An MQTT message has been received

        :param mqtt_topic: MQTT message topic
        :param payload: Payload of the message
        """
        # +1 to ignore the joining slash (prefix => prefix/)
        evt_topic = mqtt_topic[len(self._mqtt_topic) + 1:]
        if not evt_topic:
            # Empty EventAdmin topic
            _logger.debug("Empty EventAdmin topic: %s", mqtt_topic)
            return

        try:
            # Ensure that the payload is a string
            payload = to_str(payload)

            # Parse the event payload
            properties = json.loads(payload)

        except ValueError as ex:
            # Oups...
            _logger.error("Error parsing the payload of %s: %s", evt_topic, ex)
            return

        # Check framework UID of the sender
        try:
            sender_uid = to_str(properties[services.EVENT_PROP_FRAMEWORK_UID])
            if sender_uid == self._framework_uid:
                # Loop back
                return

            # Set up source UID as an extra property
            properties[EVENT_PROP_SOURCE_UID] = sender_uid

        except KeyError:
            # Not sent by us... continue
            pass

        # Update the topic if necessary
        if properties.pop(EVENT_PROP_STARTING_SLASH, False):
            # Topic has a starting '/'
            evt_topic = '/{0}'.format(evt_topic)

        # Post the event
        self._event.post(evt_topic, properties)
Пример #12
0
    def handle_mqtt_message(self, mqtt_topic, payload):
        """
        An MQTT message has been received

        :param mqtt_topic: MQTT message topic
        :param payload: Payload of the message
        """
        # +1 to ignore the joining slash (prefix => prefix/)
        evt_topic = mqtt_topic[len(self._mqtt_topic) + 1:]
        if not evt_topic:
            # Empty EventAdmin topic
            _logger.debug("Empty EventAdmin topic: %s", mqtt_topic)
            return

        try:
            # Ensure that the payload is a string
            payload = to_str(payload)

            # Parse the event payload
            properties = json.loads(payload)

        except ValueError as ex:
            # Oups...
            _logger.error("Error parsing the payload of %s: %s", evt_topic, ex)
            return

        # Check framework UID of the sender
        try:
            sender_uid = to_str(properties[services.EVENT_PROP_FRAMEWORK_UID])
            if sender_uid == self._framework_uid:
                # Loop back
                return

            # Set up source UID as an extra property
            properties[EVENT_PROP_SOURCE_UID] = sender_uid

        except KeyError:
            # Not sent by us... continue
            pass

        # Update the topic if necessary
        if properties.pop(EVENT_PROP_STARTING_SLASH, False):
            # Topic has a starting '/'
            evt_topic = '/{0}'.format(evt_topic)

        # Post the event
        self._event.post(evt_topic, properties)
Пример #13
0
    def execute(self, cmdline, stdin=sys.stdin, stdout=sys.stdout):
        """
        Executes the command corresponding to the given line
        """
        # Split the command line
        if not cmdline:
            return False

        # Convert the line into a string
        cmdline = to_str(cmdline)

        line_split = shlex.split(cmdline, True, True)
        if not line_split:
            return False

        # Prepare the I/O handler
        io_handler = IOHandler(stdin, stdout)

        try:
            # Extract command information
            namespace, command = self.get_ns_command(line_split[0])

        except ValueError as ex:
            # Unknown command
            io_handler.write_line(str(ex))
            return False

        # Get the content of the name space
        space = self._commands.get(namespace, None)
        if not space:
            io_handler.write_line("Unknown name space {0}", namespace)
            return False

        # Get the method object
        method = space.get(command, None)
        if method is None:
            io_handler.write_line("Unknown command: {0}.{1}", namespace, command)
            return False

        # Make arguments and keyword arguments
        args, kwargs = _make_args(line_split[1:])

        # Execute it
        try:
            result = method(io_handler, *args, **kwargs)
            # None is considered as a success
            return result is None or result

        except TypeError as ex:
            # Invalid arguments...
            _logger.exception("Error calling %s.%s: %s", namespace, command, ex)
            io_handler.write_line("Invalid method call: {0}", ex)
            return False

        except Exception as ex:
            # Error
            _logger.exception("Error calling %s.%s: %s", namespace, command, ex)
            io_handler.write_line("{0}: {1}", type(ex).__name__, str(ex))
            return False
Пример #14
0
    def _write_str(self, data):
        """
        Converts the given data then writes it

        :param data: Data to be written
        :return: The result of ``self.output.write()``
        """
        self.output.write(to_str(data, self.encoding))
Пример #15
0
    def _write_str(self, data):
        """
        Converts the given data then writes it

        :param data: Data to be written
        :return: The result of ``self.output.write()``
        """
        self.output.write(to_str(data, self.encoding))
Пример #16
0
    def test_dispatch(self):
        """
        Tests the dispatcher
        """
        class Servlet(routing.RestDispatcher):
            def __init__(self):
                super(Servlet, self).__init__()
                self.called_path = None
                self.prefix = None

            def reset(self):
                self.called_path = None
                self.prefix = None

            @routing.HttpGet("")
            def test_no_path(self, request, response):
                self.called_path = request.get_sub_path()
                self.prefix = request.get_prefix_path()
                response.send_content(300, "Should not happen")

            @routing.HttpGet("/")
            def test_route(self, request, response):
                self.called_path = request.get_sub_path()
                self.prefix = request.get_prefix_path()
                response.send_content(200, "OK")

            @routing.HttpGet("/test")
            def test_basic(self, request, response):
                self.called_path = request.get_sub_path()
                self.prefix = request.get_prefix_path()
                response.send_content(200, "OK")

            @routing.HttpGet("/test/a")
            def test_sub_a(self, request, response):
                self.called_path = request.get_sub_path()
                self.prefix = request.get_prefix_path()
                response.send_content(200, "OK")

            @routing.HttpGet("/test/b")
            def test_sub_b(self, request, response):
                self.called_path = request.get_sub_path()
                self.prefix = request.get_prefix_path()
                response.send_content(200, "OK")

        # Use a random prefix
        prefix = "/routing{0}".format(random.randint(0, 100))
        router = Servlet()
        self.http.register_servlet(prefix, router)

        # Route path
        for path in ("", "/", "/test", "/test/a", "/test/b"):
            router.reset()
            code, data = get_http_page(uri="{0}{1}".format(prefix, path),
                                       only_code=False)
            self.assertEqual(code, 200)
            self.assertEqual(to_str(data), "OK")
            self.assertEqual(router.called_path, path or "/")
            self.assertEqual(router.prefix, prefix)
Пример #17
0
    def _write_str(self, data):
        """
        Converts the given data then writes it

        :param data: Data to be written
        :return: The result of ``self.output.write()``
        """
        with self.__lock:
            self.output.write(to_str(data, self.encoding).encode()
                              .decode(self.out_encoding, errors="replace"))
Пример #18
0
    def _write_str(self, data):
        """
        Converts the given data then writes it

        :param data: Data to be written
        :return: The result of ``self.output.write()``
        """
        with self.__lock:
            self.output.write(to_str(data, self.encoding).encode()
                              .decode(self.out_encoding, errors="replace"))
Пример #19
0
    def __read_endpoint(self, path):
        # type: (str) -> beans.EndpointDescription
        """
        Reads the description of an endpoint at the given Z-Node path.
        Also set the endpoint event listener on the node.

        :param path: Path to the Z-Node describing the endpoint
        :return: An EndpointDescription bean
        """
        return EDEFReader().parse(
            to_str(self._zk.get(path, self._on_endpoint_event)[0]))[0]
Пример #20
0
    def connect(self, access):
        """
        Connects to the remote shell
        """
        # Connect to the server
        self._socket = socket.create_connection(access)

        # Ignore the banner
        banner = to_str(self._socket.recv(len(self._banner)))
        if banner != self._banner:
            self.fail("Incorrect banner read from remote shell")
Пример #21
0
    def connect(self, access):
        """
        Connects to the remote shell
        """
        # Connect to the server
        self._socket = socket.create_connection(access)

        # Ignore the banner
        banner = to_str(self._socket.recv(len(self._banner)))
        if banner != self._banner:
            self.fail("Incorrect banner read from remote shell")
Пример #22
0
    def __read_endpoint(self, path):
        # type: (str) -> beans.EndpointDescription
        """
        Reads the description of an endpoint at the given Z-Node path.
        Also set the endpoint event listener on the node.

        :param path: Path to the Z-Node describing the endpoint
        :return: An EndpointDescription bean
        """
        return EDEFReader().parse(
            to_str(self._zk.get(path, self._on_endpoint_event)[0])
        )[0]
Пример #23
0
    def load_index(self, force=False):
        """
        Loads the templates index

        :param force: Force index reload
        :raise IOError: Can't load the index file
        :raise ValueError: Invalid index file
        """
        if force or not self._index:
            data = to_str(self._get_file_content(self.index_url))
            index = json.loads(data)
            for key in ("home", "base"):
                self._index[key] = index["snapshots"]["cohorte-minimal-{0}-distribution".format(key)]["url"]
Пример #24
0
    def __on_message(self, client, msg):
        """
        An MQTT reply has been received
        """
        correlation_id = None
        try:
            # Parse data
            data = json.loads(to_str(msg.payload))

            # Check if we are the sender
            try:
                if data[KEY_SENDER] == self._framework_uid:
                    # We published this message
                    return
            except KeyError:
                # Not sent by us
                pass

            # Extract the correlation ID
            correlation_id = data[KEY_CORRELATION_ID]

        except ValueError as ex:
            # Unreadable reply
            _logger.error("Error reading MQTT-RPC reply: %s", ex)
            return

        except KeyError as ex:
            # No correlation ID
            _logger.error("Incomplete MQTT-RPC reply: missing %s", ex)

        try:
            # Extract result
            result = data[KEY_DATA]
            error = data[KEY_ERROR]

        except KeyError as ex:
            # Incomplete result
            result = None
            error = "Missing MQTT-RPC reply field: {0}".format(ex)

        try:
            # Find the matching proxy
            proxy = self.__waiting.pop(correlation_id)

        except KeyError:
            # No a correlation ID we know
            pass

        else:
            # Notify the proxy
            proxy.handle_result(result, error)
Пример #25
0
    def _prompt(self, prompt=None):
        """
        Reads a line written by the user

        :param prompt: An optional prompt message
        :return: The read line, after a conversion to str
        """
        if prompt:
            # Print the prompt
            self.write(prompt)
            self.output.flush()

        # Read the line
        return to_str(self.input.readline())
Пример #26
0
    def _prompt(self, prompt=None):
        """
        Reads a line written by the user

        :param prompt: An optional prompt message
        :return: The read line, after a conversion to str
        """
        if prompt:
            # Print the prompt
            self.write(prompt)
            self.output.flush()

        # Read the line
        return to_str(self.input.readline())
Пример #27
0
    def __send_message(self,
                       msgtype,
                       target,
                       message,
                       parent_uid=None,
                       target_peer=None,
                       target_group=None):
        """
        Prepares and sends a message over XMPP

        :param msgtype: Kind of message (chat or groupchat)
        :param target: Target JID or MUC room
        :param message: Herald message bean
        :param parent_uid: UID of the message this one replies to (optional)
        """
        # Convert content to JSON
        if message.subject in herald.SUBJECTS_RAW:
            content = to_str(message.content)
        else:
            # update headers
            local_peer = self._directory.get_local_peer()
            message.add_header(herald.MESSAGE_HEADER_SENDER_UID,
                               local_peer.uid)
            if target_peer is not None:
                message.add_header(herald.MESSAGE_HEADER_TARGET_PEER,
                                   target_peer.uid)
            if target_group is not None:
                message.add_header(herald.MESSAGE_HEADER_TARGET_GROUP,
                                   target_group)
            content = utils.to_json(message)

        # Prepare an XMPP message, based on the Herald message
        xmpp_msg = self._bot.make_message(mto=target,
                                          mbody=content,
                                          msubject=message.subject,
                                          mtype=msgtype)
        xmpp_msg['thread'] = message.uid
        if parent_uid:
            xmpp_msg['parent_thread'] = parent_uid

        # Store message content
        self._probe.store(herald.PROBE_CHANNEL_MSG_CONTENT, {
            "uid": message.uid,
            "content": content
        })

        # Send it, using the 1-thread pool, and wait for its execution
        future = self.__pool.enqueue(xmpp_msg.send)
        return future.result()
Пример #28
0
    def do_POST(self, request, response):
        """
        Handles a HTTP POST request

        :param request: The HTTP request bean
        :param request: The HTTP response handler
        """
        # Get the request content
        data = to_str(request.read_data())

        # Dispatch
        result = self._marshaled_dispatch(data, self._simple_dispatch)

        # Send the result
        response.send_content(200, result, 'text/xml')
Пример #29
0
    def do_POST(self, request, response):
        """
        Handles a HTTP POST request

        :param request: The HTTP request bean
        :param request: The HTTP response handler
        """
        # Get the request content
        data = to_str(request.read_data())

        # Dispatch
        result = self._marshaled_dispatch(data, self._simple_dispatch)

        # Send the result
        response.send_content(200, result, 'text/xml')
Пример #30
0
    def test_wait_publish(self):
        """
        Tests the wait_publish method
        """
        msg_topic = "pelix/test/mqtt/wait/{0}".format(str(uuid.uuid4()))
        msg_value = str(uuid.uuid4())

        # Create client
        client = mqtt.MqttClient()
        event = threading.Event()
        shared = []

        def on_connect(clt, result_code):
            if result_code == 0:
                event.set()

        def on_message(clt, msg):
            shared.append(msg)
            event.set()

        client.on_connect = on_connect
        client.on_message = on_message

        # Connect
        client.connect(MQTT_SERVER)
        client.subscribe(msg_topic)

        if not event.wait(5):
            client.disconnect()
            self.fail("Connection timeout")

        # Send message
        event.clear()
        mid = client.publish(msg_topic, msg_value, wait=True)
        client.wait_publication(mid)

        # Wait for the message to be received
        if not event.wait(5):
            client.disconnect()
            self.fail("Message not received after publication")

        # Disconnect
        client.disconnect()

        # Get the message
        msg = shared[0]
        self.assertEqual(msg.topic, msg_topic)
        self.assertEqual(to_str(msg.payload), msg_value)
Пример #31
0
    def test_wait_publish(self):
        """
        Tests the wait_publish method
        """
        msg_topic = "pelix/test/mqtt/wait/{0}".format(str(uuid.uuid4()))
        msg_value = str(uuid.uuid4())

        # Create client
        client = mqtt.MqttClient()
        event = threading.Event()
        shared = []

        def on_connect(clt, result_code):
            if result_code == 0:
                event.set()

        def on_message(clt, msg):
            shared.append(msg)
            event.set()

        client.on_connect = on_connect
        client.on_message = on_message

        # Connect
        client.connect(MQTT_SERVER)
        client.subscribe(msg_topic)

        if not event.wait(5):
            client.disconnect()
            self.fail("Connection timeout")

        # Send message
        event.clear()
        mid = client.publish(msg_topic, msg_value, wait=True)
        client.wait_publication(mid)

        # Wait for the message to be received
        if not event.wait(5):
            client.disconnect()
            self.fail("Message not received after publication")

        # Disconnect
        client.disconnect()

        # Get the message
        msg = shared[0]
        self.assertEqual(msg.topic, msg_topic)
        self.assertEqual(to_str(msg.payload), msg_value)
Пример #32
0
    def _cache_fw_host(self, fw_uid):
        # type: (str) -> str
        """
        Gets the host name associated to a framework. Caches it if necessary.
        Also, adds a watcher on the framework Z-Node

        :param fw_uid: UID of a framework
        :return: The framework host name
        """
        try:
            return self._frameworks_hosts[fw_uid]
        except KeyError:
            fw_host = self._frameworks_hosts[fw_uid] = to_str(
                self._zk.get(self._framework_path(fw_uid),
                             self._on_framework_event)[0])
            return fw_host
Пример #33
0
    def _read_loop(self):
        """
        Reads packets from the socket
        """
        while not self._stop_event.is_set():
            # Watch for content
            ready = select.select([self._socket], [], [], 1)
            if ready[0]:
                # Socket is ready
                data, sender = self._socket.recvfrom(1024)
                try:
                    data = to_str(data)
                    self._handle_packet(sender, data)

                except Exception as ex:
                    _logger.exception("Error handling the packet: %s", ex)
Пример #34
0
    def do_POST(self, request, response):
        """
        Handles a POST request

        :param request: Request handler
        :param response: Response handler
        """
        # Store data
        self.data = to_str(request.read_data())

        # Respond
        if self.error:
            response.send_content(404, 'Not active', 'text/plain')

        else:
            response.send_content(200, 'OK', 'text/plain')
    def do_POST(self, request, response):
        """
        Handles a POST request

        :param request: Request handler
        :param response: Response handler
        """
        # Store data
        self.data = to_str(request.read_data())

        # Respond
        if self.error:
            response.send_content(404, 'Not active', 'text/plain')

        else:
            response.send_content(200, 'OK', 'text/plain')
Пример #36
0
    def _read_loop(self):
        """
        Reads packets from the socket
        """
        while not self._stop_event.is_set():
            # Watch for content
            ready = select.select([self._socket], [], [], 1)
            if ready[0]:
                # Socket is ready
                data, sender = self._socket.recvfrom(1024)
                try:
                    data = to_str(data)
                    self._handle_packet(sender, data)

                except Exception as ex:
                    _logger.exception("Error handling the packet: %s", ex)
Пример #37
0
    def do_POST(self, request, response):
        """
        Handles a POST request

        :param request: Request handler
        :param response: Response handler
        """
        # Read the content
        endpoints = json.loads(to_str(request.read_data()))
        if endpoints:
            # Got something
            sender = request.get_client_address()[0]
            for endpoint in endpoints:
                self.register_endpoint(sender, endpoint)

        # We got the end points
        response.send_content(200, 'OK', 'text/plain')
Пример #38
0
    def _cache_fw_host(self, fw_uid):
        # type: (str) -> str
        """
        Gets the host name associated to a framework. Caches it if necessary.
        Also, adds a watcher on the framework Z-Node

        :param fw_uid: UID of a framework
        :return: The framework host name
        """
        try:
            return self._frameworks_hosts[fw_uid]
        except KeyError:
            fw_host = self._frameworks_hosts[fw_uid] = to_str(
                self._zk.get(
                    self._framework_path(fw_uid), self._on_framework_event
                )[0]
            )
            return fw_host
Пример #39
0
    def do_POST(self, request, response):
        """
        Handles a HTTP POST request

        :param request: The HTTP request bean
        :param request: The HTTP response handler
        """
        try:
            # Get the request content
            data = to_str(request.read_data())

            # Dispatch
            result = self._marshaled_dispatch(data, self._simple_dispatch)

            # Send the result
            response.send_content(200, result, "application/json-rpc")
        except Exception as ex:
            response.send_content(500, "Internal error:\n{0}\n".format(ex), "text/plain")
Пример #40
0
    def do_POST(self, request, response):
        """
        Handles a HTTP POST request

        :param request: The HTTP request bean
        :param response: The HTTP response handler
        """
        try:
            # Get the request content
            data = to_str(request.read_data())

            # Dispatch
            result = self._marshaled_dispatch(data, self._simple_dispatch)

            # Send the result
            response.send_content(200, result, 'application/json-rpc')
        except Exception as ex:
            response.send_content(500, "Internal error:\n{0}\n".format(ex),
                                  'text/plain')
Пример #41
0
    def __send_message(self, msgtype, target, message, parent_uid=None, target_peer=None, target_group=None):
        """
        Prepares and sends a message over XMPP

        :param msgtype: Kind of message (chat or groupchat)
        :param target: Target JID or MUC room
        :param message: Herald message bean
        :param parent_uid: UID of the message this one replies to (optional)
        """
        # Convert content to JSON
        if message.subject in herald.SUBJECTS_RAW:
            content = to_str(message.content)
        else:
            # update headers
            local_peer = self._directory.get_local_peer()
            message.add_header(herald.MESSAGE_HEADER_SENDER_UID, local_peer.uid)
            if target_peer is not None:
                message.add_header(herald.MESSAGE_HEADER_TARGET_PEER, target_peer.uid)
            if target_group is not None:
                message.add_header(herald.MESSAGE_HEADER_TARGET_GROUP, target_group)
            content = utils.to_json(message)
        
        # Prepare an XMPP message, based on the Herald message
        xmpp_msg = self._bot.make_message(mto=target,
                                          mbody=content,
                                          msubject=message.subject,
                                          mtype=msgtype)
        xmpp_msg['thread'] = message.uid
        if parent_uid:
            xmpp_msg['parent_thread'] = parent_uid

        # Store message content
        self._probe.store(
            herald.PROBE_CHANNEL_MSG_CONTENT,
            {"uid": message.uid, "content": content}
        )

        # Send it, using the 1-thread pool, and wait for its execution
        future = self.__pool.enqueue(xmpp_msg.send)
        return future.result()
Пример #42
0
    def _http_post(self, path, data):
        """
        Makes a HTTP GET request to the given path and returns the response
        as a string

        :param path: Sub path for the dispatcher servlet
        :return: A (status, response string) tuple
        """
        # Prepare the request path
        if path[0] == '/':
            path = path[1:]
        path = urljoin(self.servlet_path, path)

        # Request the end points
        conn = httplib.HTTPConnection("localhost", self.port)
        conn.request("POST", path, data, {"Content-Type": "application/json"})
        result = conn.getresponse()
        data = result.read()
        conn.close()

        # Convert the response to a string
        return result.status, to_str(data)
    def _http_post(self, path, data):
        """
        Makes a HTTP GET request to the given path and returns the response
        as a string

        :param path: Sub path for the dispatcher servlet
        :return: A (status, response string) tuple
        """
        # Prepare the request path
        if path[0] == '/':
            path = path[1:]
        path = urljoin(self.servlet_path, path)

        # Request the end points
        conn = httplib.HTTPConnection("localhost", self.port)
        conn.request("POST", path, data, {"Content-Type": "application/json"})
        result = conn.getresponse()
        data = result.read()
        conn.close()

        # Convert the response to a string
        return result.status, to_str(data)
Пример #44
0
    def get_service(self, service_name):
        """
        Retrieves the content of a service description file (like the
        FrameworkFactory service)

        :param service_name: The name of a service
        :return: The content of the service description file, or None
        """
        if not service_name:
            return None

        jar_file = zipfile.ZipFile(self.file)
        try:
            service_factory = jar_file.read('{0}/{1}'.format(
                BUNDLE_SERVICES_FOLDER, service_name))
            service_factory = to_str(service_factory)
            return service_factory.strip()
        except KeyError:
            # Not a framework JAR
            return None
        finally:
            jar_file.close()
Пример #45
0
    def get_service(self, service_name):
        """
        Retrieves the content of a service description file (like the
        FrameworkFactory service)

        :param service_name: The name of a service
        :return: The content of the service description file, or None
        """
        if not service_name:
            return None

        jar_file = zipfile.ZipFile(self.file)
        try:
            service_factory = jar_file.read(
                '{0}/{1}'.format(BUNDLE_SERVICES_FOLDER, service_name))
            service_factory = to_str(service_factory)
            return service_factory.strip()
        except KeyError:
            # Not a framework JAR
            return None
        finally:
            jar_file.close()
Пример #46
0
    def __grab_data(host, port, path):
        """
        Sends a HTTP request to the server at (host, port), on the given path.
        Returns the parsed response.
        Returns None if the HTTP result is not 200 or in case of error.

        :param host: Dispatcher host address
        :param port: Dispatcher HTTP service port
        :param path: Request path
        :return: The parsed response content, or None
        """
        # Request the end points
        try:
            conn = httplib.HTTPConnection(host, port)
            conn.request("GET", path)
            result = conn.getresponse()
            data = result.read()
            conn.close()

        except Exception as ex:
            _logger.error("Error accessing the dispatcher servlet: %s", ex)
            return

        if result.status != 200:
            # Not a valid result
            return

        try:
            # Convert the response to a string
            data = to_str(data)

            # Parse the JSON result
            return json.loads(data)

        except ValueError as ex:
            # Error parsing data
            _logger.error("Error reading the response of the dispatcher: %s",
                          ex)
Пример #47
0
        def test_properties(self):
            """
            Tests the console shell properties parameter
            """
            # Prepare some properties
            key1 = self.random_str()[:5]
            key2 = self.random_str()[:5]

            val1 = self.random_str()
            val2 = self.random_str()

            # Start the shell process
            process = subprocess.Popen(
                [sys.executable, '-m', 'pelix.shell',
                 '-D', '{}={}'.format(key1, val1), '{}={}'.format(key2, val2)],
                stdin=subprocess.PIPE, stdout=subprocess.PIPE)

            try:
                # List properties, stop and get output
                output = to_str(process.communicate(to_bytes("properties"))[0])

                found = 0
                for line in output.splitlines(False):
                    if key1 in line:
                        self.assertIn(val1, line)
                        found += 1
                    elif key2 in line:
                        self.assertIn(val2, line)
                        found += 1

                self.assertEqual(found, 2, "Wrong number of properties")
            finally:
                try:
                    # Kill it in any case
                    process.terminate()
                except OSError:
                    # Process was already stopped
                    pass
Пример #48
0
    def wait_prompt(self, raise_error=True):
        """
        Waits for the prompt to be read
        """
        data = ""
        # Wait for the prompt
        for _ in range(1, 10):
            spared = to_str(self._socket.recv(4096))
            if self._ps1 in spared:
                # Found it
                data += spared[:spared.index(self._ps1)]
                break

            else:
                # Prompt not yet found
                data += spared

        else:
            # Prompt not found
            if raise_error:
                self.fail("Didn't get the prompt")

        return data
Пример #49
0
    def do_POST(self, request, response):
        """
        Handles a POST request

        :param request: The HTTP request bean
        :param request: The HTTP response handler
        """
        # Parse the request content
        data = json.loads(to_str(request.read_data()))

        # Extract information
        uid = data['uid']
        state = data['state']
        extra = data.get('extra')

        # The response dictionary
        code = 500
        result = {'uid': uid}

        # Change the state
        try:
            self._state_dir.change_state(uid, state)
            code = 200
            result['success'] = True
        except (KeyError, ValueError) as ex:
            code = 500
            result['success'] = False
            result['message'] = str(ex)

        if state == constants.STATE_FAILED:
            # The isolate failed: print an error
            _logger.warning("Isolate '%s' sent a failure status:\n%s",
                            uid, extra)

        # Send the JSON response
        response.send_content(code, json.dumps(result), 'application/json')
Пример #50
0
    def do_POST(self, request, response):
        """
        Handles a POST request

        :param request: The HTTP request bean
        :param request: The HTTP response handler
        """
        # Parse the request content
        data = json.loads(to_str(request.read_data()))

        # Extract information
        uid = data['uid']
        state = data['state']
        extra = data.get('extra')

        # The response dictionary
        code = 500
        result = {'uid': uid}

        # Change the state
        try:
            self._state_dir.change_state(uid, state)
            code = 200
            result['success'] = True
        except (KeyError, ValueError) as ex:
            code = 500
            result['success'] = False
            result['message'] = str(ex)

        if state == constants.STATE_FAILED:
            # The isolate failed: print an error
            _logger.warning("Isolate '%s' sent a failure status:\n%s", uid,
                            extra)

        # Send the JSON response
        response.send_content(code, json.dumps(result), 'application/json')
Пример #51
0
        def test_echo(self):
            """
            Tests the console shell 'echo' method
            """
            # Get shell PS1 (static method)
            import pelix.shell.core
            ps1 = pelix.shell.core._ShellService.get_ps1()

            # Start the shell process
            process = subprocess.Popen(
                [sys.executable, '-m', 'pelix.shell'],
                stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT)

            # Avoid being blocked...
            timer = threading.Timer(5, process.terminate)
            timer.start()

            # Wait for prompt
            got = ""
            while ps1 not in got:
                char = to_str(process.stdout.read(1))
                if not char:
                    if sys.version_info[0] == 2:
                        self.skipTest("Shell console test doesn't work on "
                                      "Python 2.7 with Travis")
                    else:
                        if process.poll():
                            output = to_str(process.stdout.read())
                        else:
                            output = "<no output>"

                        self.fail("Can't read from stdout (rc={})\n{}"
                                  .format(process.returncode, output))
                else:
                    got += char

            # We should be good
            timer.cancel()

            try:
                # Try echoing
                data = self.random_str()

                # Write command
                process.stdin.write(to_bytes("echo {}\n".format(data)))
                process.stdin.flush()

                # Read result
                last_line = to_str(process.stdout.readline()).rstrip()
                self.assertEqual(last_line, data, "Wrong output")

                # Stop the process
                process.stdin.write(to_bytes("exit\n"))
                process.stdin.flush()

                # Wait for the process to stop (1 second max)
                delta = 0
                start = time.time()
                while delta <= 1:
                    delta = time.time() - start
                    if process.poll() is not None:
                        break
                    time.sleep(.1)
                else:
                    self.fail("Process took too long to stop")
            finally:
                try:
                    # Kill it in any case
                    process.terminate()
                except OSError:
                    # Process was already stopped
                    pass
Пример #52
0
    def execute(self, cmdline, stdin=sys.stdin, stdout=sys.stdout):
        """
        Executes the command corresponding to the given line
        """
        # Split the command line
        if not cmdline:
            return False

        # Convert the line into a string
        cmdline = to_str(cmdline)

        # Prepare the I/O handler
        io_handler = IOHandler(stdin, stdout)

        try:
            line_split = shlex.split(cmdline, True, True)

        except ValueError as ex:
            io_handler.write_line("Error reading line: {0}", ex)
            return False

        if not line_split:
            return False

        try:
            # Extract command information
            namespace, command = self.get_ns_command(line_split[0])

        except ValueError as ex:
            # Unknown command
            io_handler.write_line(str(ex))
            return False

        # Get the content of the name space
        space = self._commands.get(namespace, None)
        if not space:
            io_handler.write_line("Unknown name space {0}", namespace)
            return False

        # Get the method object
        method = space.get(command, None)
        if method is None:
            io_handler.write_line("Unknown command: {0}.{1}", namespace,
                                  command)
            return False

        # Make arguments and keyword arguments
        args, kwargs = _make_args(line_split[1:])

        # Execute it
        try:
            result = method(io_handler, *args, **kwargs)
            # None is considered as a success
            return result is None or result

        except TypeError as ex:
            # Invalid arguments...
            _logger.error("Error calling %s.%s: %s", namespace, command, ex)
            io_handler.write_line("Invalid method call: {0}", ex)
            self.__print_namespace_help(io_handler, namespace, command)
            return False

        except Exception as ex:
            # Error
            _logger.exception("Error calling %s.%s: %s", namespace, command,
                              ex)
            io_handler.write_line("{0}: {1}", type(ex).__name__, str(ex))
            return False

        finally:
            # Try to flush in any case
            try:
                io_handler.flush()
            except:
                pass
Пример #53
0
    def execute(self, cmdline, session=None):
        """
        Executes the command corresponding to the given line

        :param cmdline: Command line to parse
        :param session: Current shell session
        :return: True if command succeeded, else False
        """
        if session is None:
            # Default session
            session = beans.ShellSession(
                beans.IOHandler(sys.stdin, sys.stdout), {})

        assert isinstance(session, beans.ShellSession)

        # Split the command line
        if not cmdline:
            return False

        # Convert the line into a string
        cmdline = to_str(cmdline)

        try:
            line_split = shlex.split(cmdline, True, True)
        except ValueError as ex:
            session.write_line("Error reading line: {0}", ex)
            return False

        if not line_split:
            return False

        try:
            # Extract command information
            namespace, command = self.get_ns_command(line_split[0])
        except ValueError as ex:
            # Unknown command
            session.write_line(str(ex))
            return False

        # Get the content of the name space
        space = self._commands.get(namespace, None)
        if not space:
            session.write_line("Unknown name space {0}", namespace)
            return False

        # Get the method object
        method = space.get(command, None)
        if method is None:
            session.write_line("Unknown command: {0}.{1}", namespace, command)
            return False

        # Make arguments and keyword arguments
        args, kwargs = _make_args(line_split[1:], session,
                                  self._framework.get_properties())
        try:
            # Execute it
            result = method(session, *args, **kwargs)

            # Store the result as $?
            if result is not None:
                session.set(beans.RESULT_VAR_NAME, result)

            # 0, None are considered as success, so don't use not nor bool
            return result is not False
        except TypeError as ex:
            # Invalid arguments...
            self._logger.error("Error calling %s.%s: %s", namespace, command,
                               ex)
            session.write_line("Invalid method call: {0}", ex)
            self.__print_namespace_help(session, namespace, command)
            return False
        except Exception as ex:
            # Error
            self._logger.exception("Error calling %s.%s: %s", namespace,
                                   command, ex)
            session.write_line("{0}: {1}", type(ex).__name__, str(ex))
            return False
        finally:
            # Try to flush in any case
            try:
                session.flush()
            except IOError:
                pass
Пример #54
0
 def do_POST(self, request, response):
     # pylint: disable=C0103
     data = to_str(request.read_data())
     result = self._marshaled_dispatch(data, self._dispatch)
     response.send_content(200, result, "text/xml")
Пример #55
0
    def addService(self, zeroconf, svc_type, name):
        """
        Called by Zeroconf when a record is updated

        :param zeroconf: The Zeroconf instance than notifies of the
                         modification
        :param svc_type: Service type
        :param name: Service name
        """
        # Get information about the service
        info = self._get_service_info(svc_type, name)
        if info is None:
            _logger.warning("Timeout reading service information: %s - %s",
                            svc_type, name)
            return

        # Read properties
        properties = self._deserialize_properties(info.getProperties())

        try:
            sender_uid = properties[pelix.remote.PROP_ENDPOINT_FRAMEWORK_UUID]
            if sender_uid == self._fw_uid:
                # We sent this message
                return

        except KeyError:
            # Not a Pelix message
            _logger.warning("Not a Pelix record: %s", properties)
            return

        if svc_type == ZeroconfDiscovery.DNS_DISPATCHER_TYPE:
            # Dispatcher servlet found, get source info
            address = to_str(socket.inet_ntoa(info.getAddress()))
            port = info.getPort()

            self._access.send_discovered(address, port,
                                         properties['pelix.access.path'])

        elif svc_type == self._rs_type:
            # Remote service
            # Get the first available configuration
            configuration = properties[pelix.remote.PROP_IMPORTED_CONFIGS]
            if not is_string(configuration):
                configuration = configuration[0]

            # Ensure we have a list of specifications
            specs = properties[pelix.constants.OBJECTCLASS]
            if is_string(specs):
                specs = [specs]

            try:
                # Make an import bean
                endpoint = beans.ImportEndpoint(
                    properties[pelix.remote.PROP_ENDPOINT_ID],
                    properties[pelix.remote.PROP_ENDPOINT_FRAMEWORK_UUID],
                    [configuration], None, specs, properties)

            except KeyError as ex:
                # Log a warning on incomplete endpoints
                _logger.warning(
                    "Incomplete endpoint description, "
                    "missing %s: %s", ex, properties)
                return

            else:
                # Register the endpoint
                if self._registry.add(endpoint):
                    # Associate the mDNS name to the endpoint on success
                    self._imported_endpoints[name] = endpoint.uid