Speed up Rudder new node's detection - 2016 Update

In my previous article, I was proposing a way to update the new inventory list sent to Rudder more quickly.
Upon upgrading to Rudder 3.2 and CentOS 7 at the same time, this was not working anymore. It seemed that the way inventories are handled slightly changed and for some reasons inotify wasn't detecting the inventories creation anymore.
After some digging, it appears that the inventories are renamed from a temporary .davfs.xxxxx instead of being created directly in incoming directory - Seems like a webdav behaviour change in Apache 2.4.

Please find below and updated version using IN_MOVED_TO event to correctly detect new inventories sent to server - I've kept IN_CREATE event, but it shouldn't be matched anymore, you can safely remove it.

import os, datetime, subprocess, re, thread, sys
import pyinotify

inventories_path    = "/var/rudder/inventories/"
cmd_new_inv_to_cmdb = "/opt/rudder/bin/rudder agent run -b sendInventoryToCmdb"

wm = pyinotify.WatchManager() # Watch Manager
mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MOVED_TO 

def exec_sendtocmdb(file, dummy1):
    process = subprocess.Popen(cmd_new_inv_to_cmdb, stdout=subprocess.PIPE, stderr=None, shell=True)
    output = process.communicate()
    date = datetime.datetime.now()
    print("%s: %s - %s\n" % (date, file, output[0]))

class EventHandler(pyinotify.ProcessEvent):
    def process_IN_CREATE(self, event):
        date = datetime.datetime.now()
        print("%s: %s - %s created\n" % (date, event.path, event.name))

        if "incoming" in event.path:
            if ".davfs" not in event.name:
                dummy_tup = event.name, 'null'
                thread.start_new_thread(exec_sendtocmdb, dummy_tup)

    def process_IN_MOVED_TO(self, event):
        date = datetime.datetime.now()
        print "%s: %s - %s moved to" % (date, event.path, event.name)

        if "incoming" in event.path:
            if ".davfs" not in event.name:
                dummy_tup = event.name, 'null'
                thread.start_new_thread(exec_sendtocmdb, dummy_tup)

    def process_IN_DELETE(self, event):
        date = datetime.datetime.now()
        print("%s: %s - %s deleted\n" % (date, event.path, event.name))

handler = EventHandler()
notifier = pyinotify.Notifier(wm, handler)
wdd = wm.add_watch(inventories_path, mask, rec=True)


And as we're now using systemd, here is the unit file to have it running as a service and be automatically respawned in case it should crash.

Description=Rudder inventory watcher
After=syslog.target network.target



As usual, feel free to contact me if you have any question!