
from __future__ import absolute_import
from __future__ import division

import contextlib
import logging
import sys

import six

from vdsm.network.ipwrapper import IPRoute2Error
from vdsm.network.ipwrapper import Rule
from vdsm.network.ipwrapper import ruleAdd
from vdsm.network.ipwrapper import ruleDel
from vdsm.network.ipwrapper import ruleList

from . import IPRuleApi, IPRuleData, IPRuleAddError, IPRuleDeleteError


class IPRule(IPRuleApi):

    @staticmethod
    def add(rule_data):
        r = rule_data
        with _translate_iproute2_exception(IPRuleAddError, rule_data):
            ruleAdd(Rule(r.table, r.src, r.to, r.iif, prio=r.prio))

    @staticmethod
    def delete(rule_data):
        r = rule_data
        with _translate_iproute2_exception(IPRuleDeleteError, rule_data):
            ruleDel(Rule(r.table, r.src, r.to, r.iif, prio=r.prio))

    @staticmethod
    def rules():
        rules_data = ruleList()
        for rule_data in rules_data:
            try:
                r = Rule.fromText(rule_data)
                yield IPRuleData(
                    r.destination, r.source, r.srcDevice, r.table, r.prio)
            except ValueError:
                logging.warning('Could not parse rule %s', rule_data)


@contextlib.contextmanager
def _translate_iproute2_exception(new_exception, rule_data):
    try:
        yield
    except IPRoute2Error:
        _, value, tb = sys.exc_info()
        error_message = value.args[1][0]
        six.reraise(
            new_exception, new_exception(str(rule_data), error_message), tb)
