#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
traffic_control.py

Created by 4Aiur on 2011-05-30.
"""
__version__ = '0.90'


import logging
import logging.config
import json
import re
import sys
from subprocess import (call, STDOUT, PIPE, Popen)
from optparse import OptionParser
import traceback
import utils
from pdb import set_trace as breakpoints


logging.config.fileConfig('conf/logging.cfg')


class TrafficControl(object):
    """docstring for TrafficControl"""

    def __init__(self):
        self.logger = logging.getLogger(self.__class__.__name__)
        self.logger.debug('initialization')
        self.rate_file = 'conf/rate.json'
        self.filter_rule_file = 'conf/filter.json'
        self.classifier = 'u32'
        self.parent = '1:0'
        self.priority = 2
        self.nics = ['eth0', 'eth1', 'eth2', 'eth3']
        self.filters = self.load_filter()

    def pick_class_id(self, rates):
        i = 10
        ids = [int(x) for x in rates.values()]
        while True:
            if i not in ids:
                class_id = i
                break
            i += 5
        return unicode(class_id)

    def get_class_id(self, rate):
        rates = self.load_rate()
        if rate in rates:
            class_id = rates[rate]
        else:
            class_id = self.pick_class_id(rates)
            rates[rate] = class_id
            self.save_rate(rates)
            for ifname in self.nics:
                self.add_class(ifname, rate, class_id)
        return class_id

    def add_class(self, ifname, rate, class_id):
        self.logger.debug('add class ifname: %s, rate: %s, class_id: %s' \
                %(ifname, rate, class_id))
        '''
        print('/sbin/tc class add dev %s parent 1:0 classid 1:%s htb \
                rate %s burst 15Kb' % (ifname, class_id, rate))
        '''
        call('/sbin/tc class add dev %s parent 1:0 classid 1:%s htb \
                rate %s burst 15Kb' % (ifname, class_id, rate), \
                shell=True, stderr=STDOUT, stdout=None)
        '''
        print('/sbin/tc qdisc add dev %s parent 1:%s handle %s:0 sfq \
                perturb 10' % (ifname, class_id, class_id))
        '''
        call('/sbin/tc qdisc add dev %s parent 1:%s handle %s:0 sfq \
                perturb 10' % (ifname, class_id, class_id), \
                shell=True, stderr=STDOUT, stdout=None)
        return

    def load_rate(self):
        try:
            fp = open(self.rate_file)
            rates = json.loads(fp.read())
            fp.close()
        except Exception, err:
            exstr = traceback.format_exc()
            self.logger.error(err)
            self.logger.error(exstr)
            rates = {}
        return rates

    def save_rate(self, rates):
        try:
            fp = open(self.rate_file, 'w')
            result = json.dumps(rates, sort_keys=True, indent=4)
            fp.write(result + '\n')
            fp.close()
        except Exception, err:
            exstr = traceback.format_exc()
            self.logger.error(err)
            self.logger.error(exstr)
        return

    def load_filter(self):
        try:
            fp = open(self.filter_rule_file)
            filter_rules = json.loads(fp.read())
            fp.close()
        except Exception, err:
            self.logger.error(err)
            filter_rules = {}
        filters = {}
        for ipaddress in filter_rules:
            vmname = filter_rules[ipaddress]['vmname']
            ifname = filter_rules[ipaddress]['ifname']
            rate = filter_rules[ipaddress]['rate']
            flowid = filter_rules[ipaddress]['flowid']
            filters[ipaddress] = FilterRule(vmname, ifname, rate, flowid)
        return filters

    def save_filter(self, filters):
        try:
            filter_rules = {}
            for ipaddress in filters:
                filter_rule = filters[ipaddress]
                filter_rules[ipaddress] = {}
                filter_rules[ipaddress]['vmname'] = filter_rule.vmname
                filter_rules[ipaddress]['flowid'] = filter_rule.flowid
                filter_rules[ipaddress]['ifname'] = filter_rule.ifname
                filter_rules[ipaddress]['rate'] = filter_rule.rate
            fp = open(self.filter_rule_file, 'w')
            result = json.dumps(filter_rules, sort_keys=True, indent=4)
            fp.write(result + '\n')
            fp.close()
        except Exception, err: