Ejemplo n.º 1
0
def test_packet():
    # a) invalid operation.
    with pytest.raises(InvalidOperation):
        Packet(-1, b"", 0)

    # b) invalid payload -- maximum size exceeded.
    with pytest.raises(InvalidPayload):
        Packet(Op.DEBUG, b"hello" * 4096, 0)
Ejemplo n.º 2
0
def test_execute_command_invalid_tx_id():
    with Client() as c:
        monkeypatch_router(c, Packet(Op.READ, b"/local" + NUL,
                                     rq_id=0, tx_id=42))

        with pytest.raises(UnexpectedPacket):
            c.execute_command(Op.READ, b"/local" + NUL)
Ejemplo n.º 3
0
def test_client_ack():
    c = Client()

    # a) OK-case.
    c.connection.recv = lambda *args: Packet(Op.WRITE, "OK\x00")

    try:
        c.ack(Op.WRITE, "/foo", "bar")
    except PyXSError as e:
        pytest.fail("No error should've been raised, got: {0}"
                    .format(e))

    # b) ... something went wrong.
    c.connection.recv = lambda *args: Packet(Op.WRITE, "boo")

    with pytest.raises(PyXSError):
        c.ack(Op.WRITE, "/foo", "bar")
Ejemplo n.º 4
0
def test_header_decode_error():
    for backend in [UnixSocketConnection, XenBusConnection]:
        c = Client(connection=backend())

        # a) The following packet's header cannot be decoded to UTF-8, but
        #    we still need to handle it somehow.
        p = Packet(11, "/foo", rq_id=0, tx_id=128)

        try:
            c.connection.send(p)
        except UnicodeDecodeError as e:
            pytest.fail("No error should've been raised, got: {0}"
                        .format(e))
Ejemplo n.º 5
0
def test_header_decode_error(client):
    # The following packet's header cannot be decoded to UTF-8, but
    # we still need to handle it somehow.
    p = Packet(Op.WRITE, b"/foo", rq_id=0, tx_id=128)
    client.router.send(p)
Ejemplo n.º 6
0
 def recv(*args):
     if hasattr(recv, "called"):
         return Packet(Op.READ, "boo")
     else:
         recv.called = True
         return Packet(Op.WATCH_EVENT, "boo")
Ejemplo n.º 7
0
def test_client_execute_command():
    c = Client()
    c.execute_command(Op.WRITE, "/foo/bar", "baz")

    # a) arguments contain invalid characters.
    with pytest.raises(ValueError):
        c.execute_command(Op.DEBUG, "\x07foo")

    # b) command validator fails.
    c.COMMAND_VALIDATORS[Op.DEBUG] = lambda *args: False
    with pytest.raises(ValueError):
        c.execute_command(Op.DEBUG, "foo")
    c.COMMAND_VALIDATORS.pop(Op.DEBUG)

    # c) ``Packet`` constructor fails.
    with pytest.raises(InvalidPayload):
        c.execute_command(Op.WRITE, "/foo/bar", "baz" * 4096)

    # d) XenStore returned an error code.
    with pytest.raises(PyXSError):
        c.execute_command(Op.READ, "/path/to/something")

    _old_recv = c.connection.recv
    # e) XenStore returns a packet with invalid operation in the header.
    c.connection.recv = lambda *args: Packet(Op.DEBUG, "boo")
    with pytest.raises(UnexpectedPacket):
        c.execute_command(Op.READ, "/foo/bar")
    c.connection.recv = _old_recv

    # d) XenStore returns a packet with invalid transaction id in the
    #    header.
    c.connection.recv = lambda *args: Packet(Op.READ, "boo", tx_id=42)
    with pytest.raises(UnexpectedPacket):
        c.execute_command(Op.READ, "/foo/bar")
    c.connection.recv = _old_recv

    # e) ... and a hack for ``XenBusConnection``
    c = Client(connection=XenBusConnection())
    c.connection.recv = lambda *args: Packet(Op.READ, "boo", tx_id=42)
    try:
        c.execute_command(Op.READ, "/foo/bar")
    except UnexpectedPacket as e:
        pytest.fail("No error should've been raised, got: {0}"
                    .format(e))
    c.connection.recv = _old_recv

    # f) Got a WATCH_EVENT instead of an expected packet type, making
    #    sure it's queued properly.
    def recv(*args):
        if hasattr(recv, "called"):
            return Packet(Op.READ, "boo")
        else:
            recv.called = True
            return Packet(Op.WATCH_EVENT, "boo")
    c.connection.recv = recv

    try:
        c.execute_command(Op.READ, "/foo/bar")
    except UnexpectedPacket as e:
        pytest.fail("No error should've been raised, got: {0}"
                    .format(e))
    else:
        assert len(c.events) is 1
        assert c.events[0] == Packet(Op.WATCH_EVENT, "boo")

    c.connection.recv = _old_recv

    # Cleaning up.
    with Client() as c:
        c.execute_command(Op.RM, "/foo/bar")
Ejemplo n.º 8
0
    def send(self, packet):
        """
        Emulates sending a packet to xenstore by calling the equivalent WMI
        method on the XenProjectXenStoreSession WMI object. Only a few
        operations (READ, WRITE, RM, DIRECTORY) because that is all that is
        available using the WMI interface. Because the result of the WMI call
        is the equivalent of the packet received from xenstore in the Linux
        device/socket code this method stores it in a FIFO queue for later
        to be returned by the recv() method.
        """
        try:
            if not self.session:
                self._logger.debug(
                    'Attempt to send without a connection - connecting now')
                self.connect()
        except wmi.x_wmi as exc:
            six.raise_from(pyxs.PyXSError, exc)

        self._logger.debug('Sending packet to xenstore: %s', packet)

        if packet.op == Op.READ:
            try:
                result = self.session.GetValue(packet.payload)[0]
            except wmi.x_wmi as exc:
                six.raise_from(pyxs.PyXSError("session.GetValue call failed"),
                               exc)
        elif packet.op == Op.WRITE:
            payload = packet.payload.split('\x00', 1)

            try:
                self.session.SetValue(payload[0], payload[1])
            except wmi.x_wmi as exc:
                six.raise_from(pyxs.PyXSError("session.SetValue call failed"),
                               exc)

            result = "OK"
        elif packet.op == Op.RM:
            try:
                self.session.RemoveValue(packet.payload)[0]
            except wmi.x_wmi as exc:
                six.raise_from(
                    pyxs.PyXSError("session.RemoveValue call failed"), exc)

            result = "OK"
        elif packet.op == Op.DIRECTORY:
            try:
                result = self.session.GetChildren(packet.payload)[0].childNodes
            except wmi.x_wmi as exc:
                six.raise_from(
                    pyxs.PyXSError("session.GetChildren call failed"), exc)

            result = "\x00".join(result)
        else:
            raise NotImplementedError(
                "Unsupported XenStore Action ({x})".format(x=packet.op))

        self.response_packets.put(
            Packet(packet.op, result, packet.rq_id, packet.tx_id))

        # Notify that data is available
        self.w_terminator.sendall(NUL)