class oslo_messaging.Target(exchange=None, topic=None, namespace=None, version=None, server=None, fanout=None, legacy_namespaces=None)

Identifies the destination of messages.

A Target encapsulates all the information to identify where a message should be sent or what messages a server is listening for.

Different subsets of the information encapsulated in a Target object is relevant to various aspects of the API:

an RPC Server’s target:

topic and server is required; exchange is optional

an RPC endpoint’s target:

namespace and version is optional

an RPC client sending a message:

topic is required, all other attributes optional

a Notification Server’s target:

topic is required, exchange is optional; all other attributes ignored

a Notifier’s target:

topic is required, exchange is optional; all other attributes ignored

Its attributes are:

  • exchange (str) – A scope for topics. Leave unspecified to default to the control_exchange configuration option.

  • topic (str) – A name which identifies the set of interfaces exposed by a server. Multiple servers may listen on a topic and messages will be dispatched to one of the servers selected in a best-effort round-robin fashion (unless fanout is True).

  • namespace (str) – Identifies a particular RPC interface (i.e. set of methods) exposed by a server. The default interface has no namespace identifier and is referred to as the null namespace.

  • version (str) – RPC interfaces have a major.minor version number associated with them. A minor number increment indicates a backwards compatible change and an incompatible change is indicated by a major number bump. Servers may implement multiple major versions and clients may require indicate that their message requires a particular minimum minor version.

  • server (str) – RPC Clients can request that a message be directed to a specific server, rather than just one of a pool of servers listening on the topic.

  • fanout (bool) – Clients may request that a copy of the message be delivered to all servers listening on a topic by setting fanout to True, rather than just one of them.

  • legacy_namespaces (list of strings) – A server always accepts messages specified via the ‘namespace’ parameter, and may also accept messages defined via this parameter. This option should be used to switch namespaces safely during rolling upgrades.

Target Versions

Target version numbers take the form Major.Minor. For a given message with version X.Y, the server must be marked as able to handle messages of version A.B, where A == X and B >= Y.

The Major version number should be incremented for an almost completely new API. The Minor version number would be incremented for backwards compatible changes to an existing API. A backwards compatible change could be something like adding a new method, adding an argument to an existing method (but not requiring it), or changing the type for an existing argument (but still handling the old type as well).

If no version is specified it defaults to ‘1.0’.

In the case of RPC, if you wish to allow your server interfaces to evolve such that clients do not need to be updated in lockstep with the server, you should take care to implement the server changes in a backwards compatible and have the clients specify which interface version they require for each method.

Adding a new method to an endpoint is a backwards compatible change and the version attribute of the endpoint’s target should be bumped from X.Y to X.Y+1. On the client side, the new RPC invocation should have a specific version specified to indicate the minimum API version that must be implemented for the method to be supported. For example:

def get_host_uptime(self, ctxt, host):
    cctxt = self.client.prepare(server=host, version='1.1')
    return, 'get_host_uptime')

In this case, version ‘1.1’ is the first version that supported the get_host_uptime() method.

Adding a new parameter to an RPC method can be made backwards compatible. The endpoint version on the server side should be bumped. The implementation of the method must not expect the parameter to be present.:

def some_remote_method(self, arg1, arg2, newarg=None):
    # The code needs to deal with newarg=None for cases
    # where an older client sends a message without it.

On the client side, the same changes should be made as in example 1. The minimum version that supports the new parameter should be specified.