Created
December 3, 2012 07:02
-
-
Save hvnsweeting/4193258 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
#NOTE must run with sudo | |
import logging | |
import subprocess as spr | |
from pprint import pprint, pformat | |
from ConfigParser import SafeConfigParser | |
import confparser, ifaces | |
from util import get_abs_path, print_and_log_maker | |
""" | |
functions help create neccessary network manipulating command and run it | |
""" | |
log = logging.getLogger(__name__) | |
print_and_log = print_and_log_maker(log) | |
BASENUMBER_FOR_TABLE = 50 | |
def process_command(command): | |
execute_command(command) | |
def execute_command(command): | |
try: | |
command += " 2>&1" | |
resp = spr.check_output(command, shell=True) | |
except spr.CalledProcessError as e: | |
print_and_log("e", "CMD: %s \nRESP: %s " % (command, e.output)) | |
return e.output | |
else: | |
print_and_log("d", "CMD: %s \nRESP: %s " % (command, resp)) | |
return resp | |
def rule_command_factory(act, data, line=None): | |
#TODO we dont need line parameter, remove it, read pref number from rule | |
if line: | |
number_for_line = int(line[3:]) + BASENUMBER_FOR_TABLE | |
pref = data['id'] | |
try: | |
rfrom = data['from'] | |
except KeyError: | |
rfrom = "all" | |
finally: | |
cmdhead = "ip ru %s from %s " % (act, rfrom) | |
cmdmiddle = "" | |
cmdtail = "pref %s" % pref # pref is id in rule | |
try: | |
dest = data['to'] | |
except KeyError: | |
pass | |
else: | |
cmdmiddle = "to %s " % dest | |
try: | |
tableid = data['lookup'] | |
except KeyError: | |
# for failover, table_id is 50 + n (with n in WANn) | |
cmdmiddle += "lookup %s " % number_for_line | |
else: | |
# for loadbalancing, table_id is found in pr_by_dest | |
cmdmiddle += "lookup %s " % tableid | |
#TODO refactor this | |
if act == "del": | |
return "ip ru del " + cmdtail | |
else: | |
return cmdhead + cmdmiddle + cmdtail | |
def ip_rule(act, rule_data, line): | |
"""Return an ip rule command""" | |
return rule_command_factory(act, rule_data, line) | |
def generate_command(up, ruledata, line): | |
if up is True: | |
rule_para, iptable_para = "add", "A" | |
else: | |
rule_para, iptable_para = "del", "D" | |
if ruledata['type'] == "routing": | |
#print ip_rule(rule_para, ruledata, line) | |
return ip_rule(rule_para, ruledata, line) | |
elif ruledata['type'] == "nat": | |
#print iptable_command_factory(iptable_para, ruledata, line) | |
return iptable_command_factory(iptable_para, ruledata, line) | |
def iptable_command_factory(act, data, line): | |
try: | |
iface = ifaces.get_iface_of(line) | |
except KeyError, e: | |
print_and_log("e", e, line) | |
return "" | |
dport = data['port'] | |
to_ip = data['to'] | |
try: | |
comment = data['comment'] | |
except KeyError as e: | |
comment = "" | |
return "iptables -t nat -%s DNAT_PATH -i %s -p tcp -m tcp --dport %s -m comment --comment '%s' -j DNAT --to %s" %\ | |
(act, iface, dport, comment, to_ip) | |
def iptable_masq_factory(act, data): | |
# some address in config has port | |
to_ip = data['to'].split(":")[0] | |
return "iptables -t nat -A DNAT_MASQ -d %s -j MASQUERADE" % to_ip | |
def ip_ro_command_factory(table_id, lines_states, wans_weights=None): | |
# lines_states can be [wan1 wan2] or [1 2] | |
command = "ip ro replace default table %s " % table_id | |
if not wans_weights: | |
wans_weights = confparser.get_section_by_name(table_id) | |
alive_wanlines = [line for line in lines_states if lines_states[line]] | |
if len(alive_wanlines) > 0: | |
try: | |
int(alive_wanlines[0]) | |
alive_wanlines = ["wan" + str(id_) for id_ in alive_wanlines] | |
except Exception, e: | |
print e | |
tail_of_command = "" | |
for line in wans_weights: | |
if 'wan' in line and line in alive_wanlines: | |
try: | |
tail_of_command += ("nexthop via %s dev %s weight %s " % ( | |
ifaces.get_gw_of(line), | |
ifaces.get_iface_of(line), | |
wans_weights[line])) | |
except KeyError, e: | |
# bad iface | |
tail_of_command = "" | |
if tail_of_command: | |
return command + tail_of_command | |
else: | |
return "" | |
def get_all_ip_ro_command(lines_states, wandie): | |
""" | |
when wandie state is False, find all rt_tables contain it, | |
generate all ip route commands | |
Return list of ip route commands | |
""" | |
table_ids = confparser.tableids_contain(wandie) | |
ip_ro_cmds = [ip_ro_command_factory(id_, lines_states) | |
for id_ in table_ids if ip_ro_command_factory(id_, lines_states)] | |
return ip_ro_cmds | |
def delete_running_prefs(prefs): | |
for pref in prefs: | |
cmd = "ip ru | grep -e '^%s:'| wc -l" % pref | |
try: | |
counter = int(spr.check_output(cmd)) | |
except OSError as e: | |
continue | |
else: | |
for i in range(counter): | |
command = "ip ru del pref %s" % pref | |
process_command(command) | |
def flush_dnat_iptables(): | |
process_command("iptables -t nat -F DNAT_PATH") | |
process_command("iptables -t nat -F DNAT_MASQ") | |
def flush_route_cache(): | |
process_command("sleep 5 && ip ro flush cache") | |
def delete_conntrack_with_ip_of(wan_down): | |
try: | |
for i in 'sdrq': | |
cmd = "conntrack -D -%s %s >/dev/null" % ( | |
i, ifaces.get_ip_of(wan_down)) | |
process_command(cmd) | |
except KeyError, e: | |
print_and_log('e', e) | |
def main(): | |
pass | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment