Earlier this year I got involved with a small DevOps integration project for a demo. The goal was to turn monitoring data from a third-party source into something my product could use to modify our network topologies, all in true SDN fashion. On the face of it the project was small, so I could get away with making a few shortcuts (and it was only a demo, right...?), but I soon learned that if you do a small project that is interesting to people, it will get bigger, and then you are in a big coding mess.
This blog highlights some of the turns I took to clear up my mess and what we got out of some of the ideas.
The plan was something like this:
Pull in
some monitoring data, churn on it, and then make some network flow change. For example, if we detected one of those recently-made-famous elephant flows, we could move that flow away from other application data and onto a new path.
Writing the code to gather this data and do some simple processing turned out to be pretty easy. The demo was up and running fairly quickly, but once there was interest, I realized I needed to use a more sustainable model to handle changes.
I had a few basic issues. My script included code from both products, which meant it grew and grew, which hurt sustainability and further reduced my ability to reuse the code in future integrations. And for adds, moves, and changes, I was faced with the prospect of comparing data or overwriting it every time I pulled it from the source.
To fix the mess, I first turned to a home-grown message-bus system that we could use to publish the data between modules.
I built a module for the monitoring product that would publish data in a well-known format, and a module for my product that would subscribe to that data and process that same well-known format.
This one bit of modularization gave me two simple modules that could be reused again and again for other integration demos.
The published data looked something like this
myMessage = {'Parts App - Server Tier': {'containerID': 76, 'nodeIDs': [2, 9]}}
In case you didn't know, message buses are all the rage, so I assume everyone has one lying around that they can use, but if not, it occurred to me that there are plenty of cloud-based, free message buses hanging around. Take a look at something like Twitter (yes, the one that Tweets) — they have a REST API (with a bunch of Python modules), and you can send and receive secure direct messages between clients. Essentially, with a little bit of
coding
you could send and receive that JSON text from above in a message-bus-like fashion.
import twitter self.api = twitter.Api(consumer_key=self.consumerkey,consumer_secret=self.consumersecret, access_token_key=self.accesstoken, access_token_secret=self.accesstokensecret) self.api.PostDirectMessages(myMessage)
Next, I decided to use Event data as a source of the adds/moves/changes, so that I did not have to constantly process all the data. Simply put, my source module pulls in all the data at start-up and then monitors the event feed from the source, only processing a finite set of state changes. At this point in the development, I realized that now I had a generic Event bus system (available in the cloud, no less) that could be used on any system that needs the data. By that, I mean: It's not specific to my product at all.
Here is a snippet of the function I used to process the events and publish the events.
def getSwEventList(self): newtable = {} events = self.swapi.getNewEvents() for event in events: eventID = event.getEventID() # modify group event 53 if event.getEventType() == 53: newtable[eventID]['date'] = event.getEventTime() newtable[eventID]['message'] = event.getMessage() newtable[eventID]['netObjectID'] =(event.getNetObjectID()) newtable[eventID]['eventType'] = 56 …. other event types deleted…. self.publish("swEvents", newtable) return newtable
This work really helped me to simplify and modularized my code, which gave it a lot of reusability and sustainability. Coming from a C background learned in the '80s (modules are for wimps), and not working as a full-time developer anymore, I have a tendency to write top-down spaghetti code, so anything that directs my code towards modularization works for me.