gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 1 | import argparse |
| 2 | import subprocess |
| 3 | import sys |
gstepanov | f1ff52d | 2015-04-07 15:54:33 +0300 | [diff] [blame] | 4 | import socket |
| 5 | import fcntl |
| 6 | import struct |
| 7 | import array |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 8 | |
| 9 | |
gstepanov | f1ff52d | 2015-04-07 15:54:33 +0300 | [diff] [blame] | 10 | def all_interfaces(): |
| 11 | max_possible = 128 # arbitrary. raise if needed. |
| 12 | bytes = max_possible * 32 |
| 13 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
| 14 | names = array.array('B', '\0' * bytes) |
| 15 | outbytes = struct.unpack('iL', fcntl.ioctl( |
| 16 | s.fileno(), |
| 17 | 0x8912, # SIOCGIFCONF |
| 18 | struct.pack('iL', bytes, names.buffer_info()[0]) |
| 19 | ))[0] |
| 20 | namestr = names.tostring() |
| 21 | lst = [] |
| 22 | for i in range(0, outbytes, 40): |
| 23 | name = namestr[i:i+16].split('\0', 1)[0] |
| 24 | ip = namestr[i+20:i+24] |
| 25 | lst.append((name, ip)) |
| 26 | return lst |
| 27 | |
| 28 | |
| 29 | def format_ip(addr): |
| 30 | return str(ord(addr[0])) + '.' + \ |
gstepanov | 4861d71 | 2015-04-09 13:28:02 +0300 | [diff] [blame] | 31 | str(ord(addr[1])) + '.' + \ |
| 32 | str(ord(addr[2])) + '.' + \ |
| 33 | str(ord(addr[3])) |
gstepanov | f1ff52d | 2015-04-07 15:54:33 +0300 | [diff] [blame] | 34 | |
| 35 | |
| 36 | def find_interface_by_ip(ext_ip): |
| 37 | ifs = all_interfaces() |
| 38 | for i in ifs: |
| 39 | ip = format_ip(i[1]) |
| 40 | |
| 41 | if ip == ext_ip: |
| 42 | return str(i[0]) |
| 43 | |
| 44 | print "External ip doesnt corresponds to any of available interfaces" |
| 45 | return None |
| 46 | |
| 47 | |
| 48 | def make_tunnels(ips, ext_ip, base_port=12345, delete=False): |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 49 | node_port = {} |
| 50 | |
| 51 | if delete is True: |
| 52 | mode = "-D" |
| 53 | else: |
| 54 | mode = "-A" |
| 55 | |
gstepanov | f1ff52d | 2015-04-07 15:54:33 +0300 | [diff] [blame] | 56 | iface = find_interface_by_ip(ext_ip) |
| 57 | |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 58 | for ip in ips: |
| 59 | p = subprocess.Popen(["iptables -t nat " + mode + " PREROUTING " + |
gstepanov | 4861d71 | 2015-04-09 13:28:02 +0300 | [diff] [blame] | 60 | "-p tcp -i " + iface + " --dport " |
| 61 | + str(base_port) + |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 62 | " -j DNAT --to " + str(ip) + ":22"], |
| 63 | stdin=subprocess.PIPE, |
| 64 | stdout=subprocess.PIPE, |
| 65 | stderr=subprocess.STDOUT, |
| 66 | shell=True) |
| 67 | |
| 68 | out, err = p.communicate() |
| 69 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 70 | if out is not None: |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 71 | print out |
| 72 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 73 | if err is not None: |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 74 | print err |
| 75 | |
| 76 | node_port[ip] = base_port |
| 77 | base_port += 1 |
| 78 | |
| 79 | return node_port |
| 80 | |
| 81 | |
| 82 | def parse_command_line(argv): |
gstepanov | f1ff52d | 2015-04-07 15:54:33 +0300 | [diff] [blame] | 83 | parser = argparse.ArgumentParser(description= |
| 84 | "Connect to fuel master " |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 85 | "and setup ssh agent") |
gstepanov | f1ff52d | 2015-04-07 15:54:33 +0300 | [diff] [blame] | 86 | parser.add_argument( |
| 87 | "--base_port", type=int, required=True) |
| 88 | |
| 89 | parser.add_argument( |
| 90 | "--ext_ip", type=str, required=True) |
| 91 | |
| 92 | parser.add_argument( |
| 93 | "--clean", type=bool, default=False) |
| 94 | |
| 95 | parser.add_argument( |
| 96 | "--ports", type=str, nargs='+') |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 97 | |
| 98 | return parser.parse_args(argv) |
| 99 | |
| 100 | |
| 101 | def main(argv): |
| 102 | arg_object = parse_command_line(argv) |
| 103 | mapping = make_tunnels(arg_object.ports, |
gstepanov | f1ff52d | 2015-04-07 15:54:33 +0300 | [diff] [blame] | 104 | ext_ip=arg_object.ext_ip, |
gstepanov | e3481cd | 2015-04-03 21:45:52 +0300 | [diff] [blame] | 105 | base_port=arg_object.base_port, |
| 106 | delete=arg_object.clean) |
| 107 | |
| 108 | if arg_object.clean is False: |
| 109 | for k in mapping: |
| 110 | print k + " " + str(mapping[k]) |
| 111 | |
| 112 | |
| 113 | if __name__ == "__main__": |
| 114 | main(sys.argv[1:]) |