inotify

Posted by Joshua Schmidlkofer Mon, 03 Mar 2008 20:54:00 GMT

We were messing w/ Postfix and Cyrus IMAPD today. Our prime goal was making a sensical approach to authenticating against a PostgreSQL-based directory. LDAP (OpenLDAP and FDS) based tools sucks for most people. Using native-box-auth is actually quite messy. The mail data cannot be easily associated with the users. You end up with data spread everywhere.

Our basic tenants are:

  • Simple Database Schema - there is no need for a highly relational approach for something so simple.
  • Embedded procedures where possible.
  • Simple front-end.

My esteemed colleague John implemented our thoughts. He ended up with a few PGSQL functions, a couple views and a very straight-forward process.

The actual setup for IMAPD and Postfix is nearly as simple. He will be documenting it at his site later. For now, we wanted to verify the actual behaviour of postfix and imapd during SASL auth in realtime. We turned to inotify. I install pyinotify, and used thier Quick Start script. This ended up leaving me a simple script which monitored the directories which I wanted.

This will not show you files which failed to open. But it does good enough.

import os
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent

wm = WatchManager()

mask = EventsCodes.IN_DELETE | EventsCodes.IN_ACCESS | EventsCodes.IN_OPEN | EventsCodes.IN_CREATE  # watched events

class PTmp(ProcessEvent):
    def process_IN_CREATE(self, event):
        print "Create: %s" %  os.path.join(event.path, event.name)

    def process_IN_DELETE(self, event):
        print "Remove: %s" %  os.path.join(event.path, event.name)

    def process_IN_ACCESS(self, event):
        print "Access: %s" % os.path.join(event.path, event.name)

    def process_IN_OPEN(self,event):
        print "Open: %s" % os.path.join(event.path, event.name)


notifier = Notifier(wm, PTmp())
wdd = wm.add_watch('/etc', mask, rec=True)
wdd = wm.add_watch('/usr/lib/sasl2', mask, rec=True)

while True:  # loop forever
    try:
        # process the queue of events as explained above
        notifier.process_events()
        if notifier.check_events():
            # read notified events and enqeue them
            notifier.read_events()
        # you can do some tasks here...
    except KeyboardInterrupt:
        # destroy the inotify's instance on this interrupt (stop monitoring)
        notifier.stop()
        break

Stupid Cooking Tricks on Windows.

Posted by Joshua Schmidlkofer Wed, 15 Feb 2006 05:02:00 GMT

I have used Python to do many things. However, I was debugging some code for a friend and we had the strangest side effect. We were using PyCURL to read a file from a webserver, and save it to disk as part of a wxPython app that he is writing. The whole app works perfectly on Linux, but on Windows it was crashing.


Cliff tried a number of things, but he has had occasional issues w/ file writes under VMware (Which is where he runs Windows). He suspected he was hitting a write issue due to VMware, and had hit a dead end solving the problem.


I finally had an opportunity to review the problem, and I stumbled across the solution while reading the pycurl multi-file retriever. It turns out that on sane platforms (e.g. Linux) the python file object defaults to binary files. Under uber-magical windows, the file object defaults to ASCII. What a suprise. The entire problem of cooked zip files was solved by:


file('foo.zip','wb').write(data.getvalue())

Woo-hoo.
Tech Notes:
  • 'data' is a StringIO object.
  • We are using standard crap w/ pycurl.