#!/usr/bin/env python

import re
import random
import requests
import BeautifulSoup

from foldback.nagios.plugin import NagiosSNMPPlugin, NagiosPluginError
from foldback.nagios.plugin import NAGIOS_STATE_OK, NAGIOS_STATE_WARNING, NAGIOS_STATE_CRITICAL

OID_INDEX = '.1.3.6.1.4.1.2021.13.18.2.1.1'
OID_DEVICE = '.1.3.6.1.4.1.2021.13.18.2.1.2'
OID_MODEL = '.1.3.6.1.4.1.2021.13.18.2.1.3'
OID_SERIAL = '.1.3.6.1.4.1.2021.13.18.2.1.4'
OID_SIZE = '.1.3.6.1.4.1.2021.13.18.2.1.5'
OID_HEALTH = '.1.3.6.1.4.1.2021.13.18.2.1.6'
OID_HOURS = '.1.3.6.1.4.1.2021.13.18.2.1.7'


DESCRIPTION = """Check S.M.A.R.T. status

Check drive S.M.A.R.T. status with smartctl commands.

Requires smartmontools to be installed.
"""

import os


class Drive(object):
    def __init__(self, plugin, index, device):
        self.plugin = plugin
        self.index = index
        self.device = device

    def __cmp__(self, other):
        if isinstance(other, basestring):
            return cmp(self.device, other)
        if isinstance(other, Drive):
            return cmp(self.index, other.index)
        return 0

    def __repr__(self):
        return '{0} {1}'.format(self.index, self.device)

    @property
    def is_healthy(self):
        value = self.plugin.client.get('{0}.{1}'.format(OID_HEALTH, self.index))[1]
        return value == 'HEALTHY'

    @property
    def power_on_hours(self):
        return self.plugin.client.get('{0}.{1}'.format(OID_HOURS, self.index))[1]


class PluginRunner(NagiosSNMPPlugin):
    def __init__(self):
        super(PluginRunner, self).__init__(description=DESCRIPTION)
        self.add_argument('-h', '--hours', type=int, help='Drives max running hours')
        self.add_argument('-d', '--drives', action='append', help='Drives to check')

    def check_drive(self, device):
        """Check drive status

        """

        drive = self.client.find_drive(device)
        details = ''

        if drive is not None:
            if drive.is_healthy:
                self.message += '{0} OK'.format(drive)

            info = drive.get_info()
            attributes = drive.get_attributes()

            details = '{0} {1} {2}, {3} GB'.format(
                drive.device,
                info['Device model'].value,
                info['Serial number'].value,
                info['User capacity'].value / 1000 / 1000 / 1000,
            )

            try:
                hours = attributes['power_on_hours']
            except KeyError:
                self.state = NAGIOS_STATE_WARNING
                details += 'power on hours attribute not detected'
            details += ', running {0} hours'.format(hours['raw_value'])

            if self.args.hours is not None:
                if hours['raw_value'] >= self.args.hours:
                    self.state = NAGIOS_STATE_WARNING
                    self.message += ' WARN {0} running hours'.format(hours['raw_value'])

        else:
            self.state = NAGIOS_STATE_CRITICAL
            self.message += '{0} NOT FOUND'.format(device)

        self.message += ', '
        self.details.append(details)

    def check_plugin_status(self):
        """Check smart status

        """

        self.state = NAGIOS_STATE_OK
        self.details = []
        self.message = ''

        self.drives = []
        for oid, device in self.client.walk(OID_DEVICE).items():
            self.drives.append(Drive(self, oid.split('.')[-1], '{0}'.format(device)))
        self.drives.sort()

        for drive in self.drives:
            if self.args.drives and drive not in self.args.drives:
                continue

            self.message += '{0}'.format(drive.device)
            if drive.is_healthy:
                self.message += ' OK'
            else:
                self.state = NAGIOS_STATE_CRITICAL
                self.message += ' FAILED'

            if self.args.hours:
                hours = drive.power_on_hours
                if hours >= self.args.hours:
                    self.state = NAGIOS_STATE_WARNING
                    self.message += ', WARN running {0} hours'.format(hours)
                else:
                    self.message += ', running {0} hours'.format(hours)

            self.message += ', '

        self.message = self.message.rstrip(', ')

PluginRunner().run()
