Zoom: Reactive Programming with Zookeeper

In its upcoming version, Midonet will include a new storage system that we call Zoom. Zoom is a general purpose storage system for objects built on top of Zookeeper. It supports read/write operations, transactions, and referential integrity (e.g., the reference to an object is automatically cleared when that object is deleted). Zoom also offers the ability to obtain streams of updates for the objects it stores.

Midonet uses Zoom to store data such as the virtual network topology and configuration information. Agents consume streams of updates of the network topology and perform network simulation based on the latest received network state.

Streams are built on top of ReactiveX. Whenever a client, an observer in ReactiveX terminology, subscribes to a stream, the client starts receiving notifications for every update to the object corresponding to this stream. The client is also notified when the object is deleted (with an onComplete notification) and when an exception is raised.

ReactiveX lets us easily combine streams of raw devices coming straight from Zoom (e.g., bridges, routers, ports etc…) into streams of more complex network device required to perform network simulation. Streams are cached and as a consequence subscribers to a stream will obtain the last cached state of a raw device upon subscription (if the stream was opened previously). As a consequence, the number of reads issued to Zookeeper is reduced.

Using Zoom

We explain Zoom in more detail by illustrating how a host object is built. Objects in Zoom are stored as protocol-buffers. Serialization and deserialization of zoom objects is carried out in a declarative manner by tagging fields of the corresponding object class and specifying to which fields of the protocol-buffer they correspond. Here is a snippet of the host protocol-buffer and the host class:

https://gist.github.com/nschiper/cee0e70722604fc3faee#file-gistfile1-scala

The class MidoHost is tagged with @ZoomClass to indicate that an object of this class can automatically be created from an object of class TopologyHost, the class generated from the host protocol-buffer. Each field of MidoHost that corresponds to a protocol buffer field is tagged with @ZoomField. An optional converter can be specified to indicate how the conversion is performed. We explain below how the remaining fields of a host are set, namely tunnelZones and alive.

Using Zoom’s API, we obtain a stream of updates for the host object as follows:

https://gist.github.com/nschiper/8d205360f6ac954f04cb#file-gistfile1-scala

The observeOn method specifies on which thread updates are handled (so that methods accessing common data structures are scheduled on the same thread) and doOnCompleted allows us to pass a method to be execute when the host is deleted. These methods are part of the ReactiveX API.

To build the host object we merge the host stream, a stream indicating whether the host is alive or not, and the stream of tunnel zones the host is a member of. Each box in the illustration below corresponds to a method acting on update notifications:

We combine these streams as follows in Scala:

https://gist.github.com/nschiper/e0cfdbd5f5a8a98f636b#file-gistfile1-scala

The call to filter lets updates pass through only when all needed information has been gathered, namely the host object and its alive information as well as all needed tunnel zones. Depending on the update type, different actions are carried out. Among others, we handle tunnel zones that the host joined or left by respectively subscribing to and unsubscribing from these tunnel zones (not shown in this example). When all the needed information has been received, the deviceUpdated method is called:

https://gist.github.com/nschiper/57e63f36b9dcf3d9ca17#file-gistfile1-scala

This method sets the host’s IP in each one of its tunnel zones (tunnelZones is a map of identifiers and tunnel zones that is populated using the tunnel zone stream) and it converts the host protocol-buffer into the corresponding host simulation object using ZoomConvert. The alive status of the host is set and the method returns the host simulation object.

Zoom Benefits

Zoom is a general-purpose object store and offers:

  • High-availability
  • Read/Write operations and transactions
  • Automatic conversion of protocol-buffers using ZoomConvert
  • ReactiveX stream of updates for the objects it stores
  • Caching

We showed how we use Zoom in Midonet to combine several streams to build more complex objects needed for network simulation. We plan on releasing Zoom separately and hope it will be useful to the open-source community!

 

Leave a Reply

Your email address will not be published. Required fields are marked *