In the last post I left off simply connecting to the OVSDB, and sending/receiving messages. Now I want to add in a couple things:
1) Handling of Echo messages – There should be periodic Echo messages sent back and forth between my client and the ovsdb-server
2) Handling of updates – When we issue a command like `monitor`, not only do we get a snapshot of the database at that time, but we also register ourselves for updates. So I’d like the client to keep listening for updates to OVSDB and allow me to see them
Using the `recv` socket command like we did in the beginning would require the client to keep looping around waiting for a message and that doesn’t seem very efficient. Instead I’m going to leverage select. What `select` will let me do is to wait for incoming data, then take action when we hear something, or take action when there is outgoing data waiting to be processed. Here’s an example:
def listen_for_messages(sock, message_queues): # To send something, add a message to queue and append sock to outputs inputs = [sock, sys.stdin] outputs =  while sock: readable, writable, exceptional = select(inputs, outputs, ) for s in readable: if s is sock: data = sock.recv(4096) message_queues[sock].put(data) outputs.append(sock) print "recv:" + data elif s is sys.stdin: print sys.stdin.readline() sock.close() return else: print "error" for w in writable: if w is sock: sock.send(message_queues[sock].get_nowait()) outputs.remove(sock) else: print "error"
To start things off, I create a few lists that will hold the inputs and outputs I plan to monitor. In this function I initialize the inputs to be the socket connection and stdin, and outputs are empty. Next I create a while loop that will run as long as the socket is open: `while sock:`. Now we get to the select statement. I pass in the inputs and outputs that will be monitored, and the select will return whatever inputs or outputs have data that need to be processed: `readable, writable, exceptional = select(inputs, outputs, )`
If there are any inputs, they will be assigned to the variable `readable` and we will enter the first for loop. There we check to see if there is socket data or stdin data. When we get data on a socket, we will simply copy that data into our message queue (this is a quick and dirty way to reply to an echo), and put the socket into the output list. If its something from stdin (i.e. user entering stuff on the keyboard), I will just close the socket for now. As you can imagine, one could easily use this to allow the user to send commands to the ovsdb-server with some extra modification.
Now I handle the output list, much the same way I did the input list. In this case, if there is socket data in the output list, I pull the data off the message queue, and send it out the socket. Then I remove the socket from the output queue to leave it empty again.
That should take care of our basic message handler. Using select, we’re able to handle various inputs and outputs in a efficient manner, and in this case, receive and send echo messages. This will keep the connection to the ovsdb-server alive for us. Also, if we had issued a monitor command, it will receive those updates from the server and print them to screen.
If another function wants to send messages out to the server, we would need to slightly modify things so that we can add messages to the queue and put the socket into the output list. I’ve posted a modified version of this code on github where you can have a look if interested: https://github.com/fredhsu/py-ovsdb-client