190 Commits

Author SHA1 Message Date
Mark McLoughlin
2abb40f9e9 Add a context serialization hook
The client call() and cast() methods take a request context argument
which is expected to be a dictionary. The RPC endpoint methods on the
server are invoked with a dictionary context argument.

However, Nova passes a nova.context.RequestContext on the client side
and the oslo-incubator RPC code deserializes that as a amqp.RpcContext
which looks vaguely compatible with Nova's RequestContext.

Support the serialization and deserialization of RequestContext objects
with an additional (de)serialize_context() hook on our Serializer class.

Note: this is a backwards incompatible API change because Serializer
implementations which do not implement the new abstract methods would
no longer be possible to instantiate. Not a problem with this commit,
but shows the type of compat concerns we'll need to think about once the
API is locked down for good.

Change-Id: I20782bad77fa0b0e396d082df852ca355548f9b7
2013-08-09 08:24:49 +01:00
Mark McLoughlin
bf171ede28 Document how call() handles remote exceptions
This is tricky stuff, so document it carefuly.

Related-Bug: #1162063
Change-Id: Id197bf87e9a7ed222508efe5d5246003ac02680e
2013-08-07 13:22:15 +01:00
Mark McLoughlin
ac2176cde3 Add a per-transport allow_remote_exmods API
Currently we have a allowed_rpc_exception_modules configuration variable
which we use to configure a per-project list of modules which we will
allow exceptions to be instantiated from when deserializing remote
errors.

It makes no sense for this to be user configurable, instead the list of
modules should be set when you create a transport.

Closes-Bug: #1031719
Change-Id: Ib40e92cb920996ec5e8f63d6f2cbd88fd01a90f2
2013-08-07 13:11:46 +01:00
Mark McLoughlin
66f597f30d Expose RemoteError exception in the public API
If a remote endpoint raises an exception which the client is not allowed
to (or cannot) deserialize, then RPCClient.call() raises a RemoteError
exception instead.

Make this exception type part of the public API.

Change-Id: I70be0ab7d40af3224d93d6bd0522c1a82f6303c3
2013-08-07 12:52:58 +01:00
Mark McLoughlin
9ac9f615b2 Implement failure replies in the fake driver
Change-Id: Ifd9ede7cb17a471ae2f9024b49ef6bbdc645476a
2013-08-07 12:52:58 +01:00
Mark McLoughlin
f6df32d943 Add API for expected endpoint exceptions
Review I4e7b19dc730342091fd70a717065741d56da4555 gives a lot of the
background here, but the idea is that some exceptions raised by an RPC
endpoint method do not indicate any sort of failure and should not be
logged by the server as an error.

The classic example of this is conductor's instance_get() method raising
InstanceNotFound. This is perfectly normal and should not be considered
an error.

The new API is a decorator which you can use with RPC endpoints methods
to indicate which exceptions are expected:

    @messaging.expected_exceptions(InstanceNotFound)
    def instance_get(self, context, instance_id):
        ...

but we also need to expose the ExpectedException type itself so that
direct "local" users of the endpoint class know what type will be used
to wrap expected exceptions. For example, Nova has an ExceptionHelper
class which unwraps the original exception from an ExpectedException and
re-raises it.

I've changed from client_exceptions() and ClientException to make it
more clear it's intent. I felt that the "client" naming gave the
impression it was intended for use on the client side.

Change-Id: Ieec4600bd6b70cf31ac7925a98a517b84acada4d
2013-08-07 12:52:54 +01:00
Mark McLoughlin
206c19e99e Add a driver method specifically for sending notifications
Notifications are an unusual case in that we need users to manually opt
in to new incompatible message formats by editing configuration because
there may be external consumers expecting the old format.

Add a send_notification() method to the driver interface and add a
format version paramater to the method, to make it clear that this
version selection is specifically for notifications.

In the case of the rabbit/qpid drivers, the 2.0 format is where we added
the message envelope.

Change-Id: Ib4925c308b1252503749962aa16f043281f2b429
2013-08-07 06:51:35 +01:00
Mark McLoughlin
294c99a6d2 Enforce target preconditions outside of drivers
The target preconditions (e.g. you need at least a topic to send) are
the same for all drivers, so enforce them before we ever call into a
driver.

Change-Id: Ic4e9bd94bd9f060ec0662d2bb778c699903dddc4
2013-08-07 06:51:24 +01:00
Mark McLoughlin
89079c6ea1 Add comments to ReplyWaiter.wait()
This method is fairly gnarly, so break my usual preference to make the
intent clear from the code and instead include detailed comments in the
method.

Change-Id: I107272a7eab85c70581652488a3c14ce0e18b906
2013-08-07 06:51:24 +01:00
Mark McLoughlin
b516271a80 Remove some FIXMEs and debug logging
These FIXMEs don't need fixing now that I think it through some more.
The reply format is specific to drivers and the 'ending' flag is part of
the existing wire protocol that we need to support even if we don't
support multicall().

Change-Id: I834f0bb01513b5318f0b365948a7d9247feb49bf
2013-08-07 06:51:24 +01:00
Mark McLoughlin
84a0693737 Remove unused IncomingMessage.done()
We appear to not have a use for this. I had originally thought we might
use this to ack messages one they've been processed and replied to, but
we actually have always acked messages as soon as they have been
deserialized and queued for dispatching.

Change-Id: I8e1fd565814f3b5e3ba0f1bc77e62ed52ff08661
2013-08-07 06:51:24 +01:00
Mark McLoughlin
7c305150ff Implement wait_for_reply timeout in rabbit driver
Note - the tests use timeout=0.01 because timeout=0 doesn't seem to be
working for some reason.

Change-Id: I814a3decdad5ddce0a1a2301ba2d59fa928b53a7
2013-08-07 06:51:03 +01:00
Mark McLoughlin
cb2623f46e Use testtools.TestCase assertion methods
I typically avoided using e.g. assertIsNone() thinking we couldn't use
it on 2.7, but now that we use testtools.TestCast there are a bunch of
useful assertion methods we can use.

Change-Id: I7696dc4744cdfd2466773326f202bc08dcfcbf0f
2013-08-07 06:43:55 +01:00
Mark McLoughlin
3471e02b4a Implement failure replies in rabbit driver
Make the rabbit driver properly serialize exceptions before sending them
back in a reply and then properly re-raise them on the client side.

Also, extend the rabbit driver test to cover this case.

Change-Id: I6b3d03edcd41810125ba6442db5515754f0c1ac9
2013-08-05 13:15:54 +01:00
Mark McLoughlin
a823368b72 Add test with multiple waiting sender threads
The trickiest logic in the rabbit driver is to handle the situation
where multiple threads are waiting for a reply on the same reply queue.

This commit adds unit testing for that scenario and fixes some bugs with
it.

Change-Id: I5c8fbeec49572a4f3badbcdae414dc44dc690b6a
2013-08-05 13:15:54 +01:00
Mark McLoughlin
a3a684d2c9 Fix race condition in ReplyWaiters.wake_all()
While we're iterating over the queues in ReplyWaiters.wake_all(), new
queues can be registered and we get:

  RuntimeError: dictionary changed size during iteration

Instead of using an iterator, take a snapshot list of message IDs and
operate on that.

We don't actually care about any new queues added after wake_all() is
called because the connection lock has already been dropped so one of
the other waiters must have picked it up.

We also don't need to worry about queues being removed - if we write to
a removed queue, that's not going to be a problem.

Change-Id: Ib572cbfd3a7346b76579f82b64aa85a03c1a4fb2
2013-08-05 13:15:54 +01:00
Mark McLoughlin
950c37c595 Add rabbit unit test for sending and receiving replies
Change-Id: I9574940904673257317a0caa86c585459e066ff7
2013-08-05 13:15:54 +01:00
Jenkins
96564b5f58 Merge "Add tests for rabbit driver wire protcol" 2013-08-05 10:57:42 +00:00
Jenkins
2f1b87d2f0 Merge "Pop _unique_id when checking for duplicates" 2013-08-05 10:06:06 +00:00
Jenkins
245d783623 Merge "Add a transport cleanup() method" 2013-08-05 10:05:07 +00:00
Mark McLoughlin
8572d78faf Add tests for rabbit driver wire protcol
Add two test cases:

  - send messages using the rabbit driver and check that the message
    gets sent to the expected queue in the expected format

  - send messages to a given queue in the correct format and check that
    we can happily consume them using the rabbit driver

i.e. these are tests that check that the driver sends and receives
messages according to the wire protocol.

Change-Id: I6a48085585981b17609b31f216bdca438e90e068
2013-08-02 06:48:01 +01:00
Mark McLoughlin
8b366b3001 Pop _unique_id when checking for duplicates
Drivers should not be returning messages with any driver-specific
wire format fields included. Right now, the rabbit and qpid drivers are
leaking the _unique_id field.

Avoid this simply by popping _unique_id when we're checking for dups.

Change-Id: Icbfb02ee66aebe5ef97a9a2502d8a0745e07bd8b
2013-08-02 06:48:01 +01:00
Mark McLoughlin
1f0874857c Add a transport cleanup() method
Pretty obvious that we need this.

The rabbit/qpid implementations just empty the connection pool, in the
same way their module-level cleanup() methods do now.

Change-Id: I70ba5cab3eb7a30f74cdd6cafe60087769a77b57
2013-08-02 06:47:57 +01:00
Mark McLoughlin
03fcbe6ca6 Remove my notes and test scripts
These aren't really appropriate for dumping in the repo like this
so I've moved them here:

  https://github.com/markmc/oslo.messaging-notes

Change-Id: Iba4c19cefd8a02831543d5c2c3b1886d5d31fa63
2013-07-31 07:24:40 +01:00
Jenkins
e987525dc0 Merge "Add initial qpid driver" 2013-07-31 06:15:29 +00:00
Jenkins
6312930974 Merge "Move most new rabbit driver code into amqpdriver" 2013-07-31 06:14:37 +00:00
Jenkins
30d21c5880 Merge "Move rpc_conn_pool_size into amqp" 2013-07-31 06:11:54 +00:00
Jenkins
b9e09ac906 Merge "Add simple rabbit driver unit test" 2013-07-31 06:11:32 +00:00
Jenkins
71e1072bb5 Merge "Temporarily add eventlet to requirements" 2013-07-31 06:10:51 +00:00
Jenkins
fca4b21ffb Merge "Add exception serialization tests" 2013-07-31 06:10:19 +00:00
Mark McLoughlin
da539a094d Add initial qpid driver
This just adds a QpidDriver which re-uses AMQPDriver.

The test-rabbit-{client,server}.py test scripts works fine with this
driver and the URL changed to qpid:///

Change-Id: Ifb72853e83b678b311fecb21fe016af19a67b272
2013-07-31 07:06:55 +01:00
Mark McLoughlin
85a386765f Move most new rabbit driver code into amqpdriver
All of this code should be reusable by the rabbit driver.

Change-Id: Ib09e467313c9b68f1eba6b615e6fce83f44fee70
2013-07-31 07:06:16 +01:00
Jenkins
653e8ac836 Merge "Remove unused file" 2013-07-31 06:02:14 +00:00
Jenkins
a7ec87420f Merge "Add unit tests for object pool" 2013-07-31 06:00:30 +00:00
Jenkins
377fa049fd Merge "Remove only_free param to Pool.get()" 2013-07-31 05:59:47 +00:00
Mark McLoughlin
7bd60904f8 Move rpc_conn_pool_size into amqp
This is used in amqp.py, it shouldn't be registered in impl_rabbit.py.

Change-Id: I259f074019dd1bd7c210f84548bc5d4933b6aa89
2013-07-29 07:04:54 +01:00
Mark McLoughlin
5be559405a Add simple rabbit driver unit test
Change-Id: I1ae6b31f422f8a6e17c985d64a830b7475e7d97e
2013-07-27 15:54:06 +01:00
Mark McLoughlin
576ce35e14 Temporarily add eventlet to requirements
We absolutely do not want this to be a requirement, but for the moment
the rabbit and qpid drivers import eventlet and avoid using it at
runtime. This should be cleaned up shortly and we can remove the dep
again.

Change-Id: Iaef75964a502598a94d95aa77f0e44d1f7faba50
2013-07-27 15:54:03 +01:00
Mark McLoughlin
4043506a23 Add missing gettextutils
We don't need this in oslo.messaging itself, but excutils and sslutils
do use it.

Change-Id: Ib35caa6616aab7be1a7f872b2073f7b9f606b258
2013-07-27 15:49:48 +01:00
Mark McLoughlin
8ace474e3c Add unit tests for object pool
This should be complete coverage of the new pool.Pool class.

Change-Id: I439e3d0adc4e370358db62573f862bf6caa8600f
2013-07-27 15:43:29 +01:00
Mark McLoughlin
abf5b2bf5a Remove only_free param to Pool.get()
This is unused. I think I added it before iter_free(), i.e. empty()
was going to be:

  for item in self.get(only_free=True):
      item.close()

rather than:

  for item in self.iter_free():
      item.close()

Change-Id: Ie6d0de3b7453ee036412db10f37d26f04de73cf7
2013-07-27 15:43:29 +01:00
Mark McLoughlin
45ab8699a6 Connection pool bugfix
This is only seen if you try to call amqp.cleanup().

Change-Id: I5c14a21987b4b7aeca7dddc91d7c8b2510edefeb
2013-07-26 07:41:09 +01:00
Mark McLoughlin
e39ccfae01 Remove unused file
Change-Id: Ibff776b694d354f9465cc9f476275103508dcde8
2013-07-26 07:06:48 +01:00
Mark McLoughlin
7d16c76b23 Add exception serialization tests
These are pretty comprehensive tests for the exception serialization
code. The code itself code do with a bunch of refactoring, but that will
come later.

The main TODO item is that we need a way for users of the API to
register the list of modules that it wants to allow exceptions to be
deserialized from. There is no need for this to be an end-user
configuration option, but we do need each service to be able to specify
its own list.

Change-Id: Ib2fc3f1ca5da708b41bdc00e8ac6ce0c92399ce8
2013-07-26 06:55:15 +01:00
Mark McLoughlin
c719dc306b Don't call consume() each time iterconsume() is called
We're going to be using iterconsume(limit=1) and this basically seems
to be broken right now because you get an error if you call consume()
multiple times on the same connection.

Set the 'do_consume' flag at connection time rather than on entry into
iterconsume().

Change-Id: I988e4074ae0e267384931d6e1994e9cbe5248196
2013-07-24 08:15:35 +01:00
Mark McLoughlin
29dcc87052 Add test code for the rabbit driver
These are just a couple of silly sample scripts. Proper unit tests will
follow.

Change-Id: I6f27ae071c7e6f96059fd665d1163c89227833b9
2013-07-24 08:15:35 +01:00
Mark McLoughlin
8ccb5741d2 Remove use of gettextutils
We don't have any infrastructure for localizations in oslo.messaging
so using this is pointless right now. I'm also generally not convinced
we want to translate any of the strings in this library anyway.

For now, just add a dummy _() function. We can can unmark the strings
later.

Change-Id: I1b6a698ee5558c50dc5eafee1f5f05ee2570435e
2013-07-24 08:15:35 +01:00
Mark McLoughlin
b7350fa229 Add initial rabbit driver
There's obviously an awful lot of work left to do on this. Some 20
FIXMEs, for a start :)

However, the test client can successfully invoke a call() and get a
reply back from the server!

The main complexity is in how the client waits for a reply, especially
where there are multiple threads all waiting for replies. Rather than
follow the current method of spawning off a greenthread (and the implied
dependency on eventlet) to read the replies and pass them to the queue
for the appropriate waiting thread, we instead have one of the waiting
threads take on that responsibility.

Change-Id: I20d3d66a5cc9820752e7eaebd8871ffb235d31c9
2013-07-24 08:15:35 +01:00
Mark McLoughlin
c891e7ee24 Remove use of openstack.common.local
This means we no longer set the request context for the current thread
so that it can be used in logging.

We do need to add this back later, but it might be in the form of a
get_current_context() method.

Change-Id: I3f08a85e2019affddec829e2ea008b5c10707660
2013-07-24 08:15:35 +01:00
Mark McLoughlin
1a7e51eb4a Use stdlib logging
I guess this loses us automatic logging of details from request context.

Change-Id: I7413f025231c14b7cbdc9e90099407bc6c7943e1
2013-07-24 08:15:35 +01:00