#!/usr/bin/python

import re
import os
import sys
import syslog
import tempfile
import traceback

def find_disks():
    regmount = re.compile('([^ ]+)[ \t]+([^ ]+)[ \t]+([^ ]+)[ \t]+([^ ]+)[ \t]+[0-9]+[ \t]+[0-9]+')
    regdisks = re.compile('(/dev/([sh][a-z]+|md[0-9]+))')

    disks = set()

    for ln in file('/proc/mounts').readlines():
        m = regmount.match(ln)

        if m is not None:
            dev, mnt = m.group(1), m.group(2)

            if not dev.startswith('/dev/') or dev.startswith('/dev/loop') or not mnt.startswith('/'):
                continue

            if os.path.islink(dev):
                dev = os.path.normpath(os.path.join(os.path.dirname(dev), os.readlink(dev)))

            devm = regdisks.match(dev)

            if devm is not None:
                disk = devm.group(1)

                if devm.group(2).startswith('md'):
                    sdevs = os.listdir('/sys/block/' + devm.group(2) + '/slaves')
                    for sdev in sdevs:
                        devm2 = regdisks.match('/dev/' + sdev)
                        if devm2 is not None:
                            disks.add(devm2.group(1))
                else:
                    disks.add(disk)

    return disks

cfgname = '/etc/smartd.conf'
tmpname = cfgname + '.new'
bakname = cfgname + '.orig'

try:
    disks = find_disks()

    regscan = re.compile('^DEVICESCAN')
    regcomm = re.compile('[ ]*#')

    tmpfile = open(tmpname, 'w')

    for ln in file(cfgname).readlines():
        m1 = regcomm.match(ln)
        if m1 is not None:
            tmpfile.write(ln)
        else:
            m2 = regscan.match(ln)
            if m2 is not None:
                tmpfile.write('#' + ln)

    for disk in disks:
        tmpfile.write(disk + ' -m <nomailer> -M exec /bin/true\n')

    tmpfile.close()

    if not os.access(bakname, os.F_OK):
        os.rename(cfgname, bakname)

    os.rename(tmpname, cfgname)

except Exception, e:
    syslog.openlog('sng-update-smartd', syslog.LOG_USER)
    syslog.syslog(syslog.LOG_CRIT, 'unable update smartd configuration: ' + str(e))
    for ln in traceback.format_list(traceback.extract_tb(sys.exc_traceback)):
        syslog.syslog(syslog.LOG_CRIT, '    ' + ln)
    syslog.closelog()
    print >> sys.stderr, 'error: ' + str(e)

    try:
        os.unlink(tmpname)
    except:
        pass

    sys.exit(1)

sys.exit(0)
