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.
#!/usr/bin/python
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)
notifier.loop()
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.
[Unit]
Description=Rudder inventory watcher
After=syslog.target network.target
[Service]
Type=simple
Environment=PYTHONUNBUFFERED=true
ExecStart=/sbin/rudder-inventory-watcher
PrivateTmp=true
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
As usual, feel free to contact me if you have any question!