# Copyright (c) 2015 iXsystems, Inc.
# All rights reserved.
# This file is a part of TrueNAS
# and may not be copied and/or distributed
# without the express permission of iXsystems.

import os
import json
import subprocess
import xmlrpclib

from django.utils.translation import ugettext as _

from freenasUI.failover.enc_helper import LocalEscrowCtl
from freenasUI.middleware.notifier import notifier
from freenasUI.system.alert import alertPlugins, Alert, BaseAlert

FAILOVER_JSON = '/tmp/failover.json'


class FailoverCheckAlert(BaseAlert):

    def run(self):

        alerts = []

        if not notifier().failover_licensed():
            return alerts

        try:
            s = notifier().failover_rpc()
            if s is not None:
                s.run_sql("SELECT 1", None)
        except xmlrpclib.Fault, e:
            if e.faultCode == 5:
                return [Alert(Alert.CRIT, _(
                    'Failover access denied. Please reconfigure it.'
                ))]
            elif e.faultCode == 55:
                return [Alert(Alert.CRIT, _(
                    'TrueNAS versions mismatch in failover. '
                    'Update both nodes to the same version.'
                ))]
            else:
                raise
        except Exception, e:
            alerts.append(Alert(Alert.CRIT, _(
                'Failed to check failover status with the other node: %s' % (
                    e,
                )
            )))

        status = notifier().failover_status()

        fobj = None
        try:
            with open(FAILOVER_JSON, 'r') as f:
                fobj = json.loads(f.read())
        except:
            pass

        if status == 'ERROR':
            errmsg = None
            if os.path.exists('/tmp/.failover_failed'):
                with open('/tmp/.failover_failed', 'r') as fh:
                    errmsg = fh.read()
            if errmsg:
                errmsg = _("Failover failed: %s") % errmsg
            else:
                errmsg = _("Failover failed")
            alerts.append(Alert(
                Alert.CRIT,
                errmsg,
            ))
        elif status not in ('MASTER', 'BACKUP', 'SINGLE'):
            alerts.append(Alert(
                Alert.WARN, _(
                    'Could not determine external failover link status, check '
                    'cabling.'
                ),
            ))
        p1 = subprocess.Popen(
            ["/sbin/ifconfig", "carp1"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        stdout = p1.communicate()[0]
        if status != "SINGLE" and stdout.find("carp: INIT") != -1:
            alerts.append(Alert(
                Alert.CRIT, _(
                    'Could not determine internal failover link status, '
                    'Automatic failover disabled.'
                ),
            ))

        if status != "SINGLE":
            try:
                if notifier().sysctl('kern.cam.ctl.ha_link') == 1:
                    alerts.append(Alert(
                        Alert.CRIT, _('CTL HA link is not connected'),
                    ))
            except:
                pass

        if status == 'MASTER':
            masters, backups = notifier().get_carp_states()
            if len(backups) > 0:
                alerts.append(Alert(
                    Alert.WARN,
                    _('Check external failover links.'),
                ))

        if status == 'BACKUP':
            try:
                if len(fobj['phrasedvolumes']) > 0:
                    escrowctl = LocalEscrowCtl()
                    if not escrowctl.status():
                        alerts.append(Alert(
                            Alert.CRIT, _(
                                'No escrowed passphrase for failover. '
                                'Automatic failover disabled.'
                            ),
                        ))
                        # Kick a syncfrompeer if we don't.
                        s = notifier().failover_rpc()
                        passphrase = s.enc_getkey()
                        if passphrase:
                            escrowctl.setkey(passphrase)
            except:
                pass
        return alerts

alertPlugins.register(FailoverCheckAlert)
