#!/usr/bin/python import os import dbus import pwd import sys # Urgencies URGENCY_LOW = 0 URGENCY_NORMAL = 1 URGENCY_CRITICAL = 2 def setup(): try: # smartd should have these global smartd_device smartd_device = os.environ['SMARTD_DEVICE'] global smartd_devicestring smartd_devicestring = os.environ['SMARTD_DEVICESTRING'] global smartd_failtype smartd_failtype = os.environ['SMARTD_FAILTYPE'] except: exit(1) # What users we want to notify def testuser(param): # The default user's id is 1000 and the next created ones increment from there return ((param[2]>=1000) and (param[2])<=10000) # The uid is at index #2 def getuids(pwd): return pwd[2] # Returns the list of "real" users of the computer def getusers(): users = pwd.getpwall() filtered = filter(testuser,users) return map(getuids,filtered) # We are forced to fork for this activity once per user you want to notify. def notifyusers(message,urg): users = getusers() for user in users: pid = os.fork() if pid: os.waitpid(pid, 0) else: #setuid os.setuid(user) # Notify this user notify(message,urg) sys.exit(0) # The notification itself def notify (message,urg): # D-bus settings BUS_NAME = 'org.freedesktop.Notifications' OBJ_PATH = '/org/freedesktop/Notifications' IFACE_NAME = 'org.freedesktop.Notifications' bus = dbus.SessionBus() notify_obj = bus.get_object(BUS_NAME,OBJ_PATH) notifications = dbus.Interface(notify_obj,IFACE_NAME) # Explained further at http://www.galago-project.org/specs/notification/0.9/index.html hints = {"urgency":urg} notifications.Notify('Hard drive health monitoring agent',0,'/usr/share/icons/Tango/scalable/status/important.svg','Potential hard disk failure!',message,[],hints,0) # Returns error message and priority in list def geterrordetails(failtype): msg = { "EmailTest": ["This is an email test message.",URGENCY_LOW], "Health": ["The SMART health status indicates imminent failure.",URGENCY_CRITICAL], "Usage": ["A usage Attribute has failed.",URGENCY_NORMAL], "SelfTest": ["The number of self-test failures has increased.",URGENCY_NORMAL], "ErrorCount": ["The number of errors in the ATA error log has increased.",URGENCY_NORMAL], "CurrentPendingSector": ["One of more disk sectors could not be read and are marked to be reallocated (replaced with spare sectors).",URGENCY_NORMAL], "OfflineUncorrectableSector": ["During off-line testing, or self-testing, one or more disk sectors could not be read.",URGENCY_NORMAL], "FailedHealthCheck": ["The SMART health status command failed.",URGENCY_NORMAL], "FailedReadSmartData": ["The command to read SMART Attribute data failed.",URGENCY_NORMAL], "FailedReadSmartErrorLog": ["The command to read the SMART error log failed.",URGENCY_NORMAL], "FailedReadSmartSelfTestLog": ["The command to read the SMART self-test log failed.",URGENCY_NORMAL], "FailedOpenDevice": ["The open() command to the device failed.",URGENCY_NORMAL]} i = msg.get(failtype,["Internal error in monitoring agent.",URGENCY_LOW]) return i[0],i[1] # The main logic def main(): setup() msg,urgency = geterrordetails(smartd_failtype) message = "The hard drive SMART monitoring agent has detected a potential problem with your hard disc "+smartd_devicestring+". The message given was: "+msg notifyusers(message,urgency) main()