-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathip-control.py
More file actions
executable file
·152 lines (137 loc) · 4.62 KB
/
ip-control.py
File metadata and controls
executable file
·152 lines (137 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/python
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, \
SimpleJSONRPCRequestHandler
import argparse
from ip_control import configuration
import os
import os.path
import signal
import logging
import logging.config
parser = argparse.ArgumentParser(description = 'Manages dynamic IP routes for hosted LXCs.')
parser.add_argument('--example-cfg', dest = 'print_config', action = 'store_true',
help = 'Prints out an example configuration.')
parser.add_argument('--config', '-c', dest = 'config', type = str, default = '/etc/ip-control.conf',
help = 'Specify alternate config file.')
parser.add_argument('--log-to', '-l', dest = 'logging', nargs = '+', type = str, default = ['console'],
help = 'Specify logging output. Possible values are console and syslog')
args = parser.parse_args()
if args.print_config:
# Create example configuration
configuration.write_example()
exit(0)
# Init logging
logging.config.dictConfig({
'version': 1,
'formatters': {
'default': {
'format': "ip-control - %(levelname)s: %(message)s"
},
'console': {
'format': "%(asctime)s - %(levelname)s: %(message)s"
}
},
'handlers': {
'syslog': {
'class': 'logging.handlers.SysLogHandler',
'formatter': 'default',
'address': '/dev/log'
},
'console': {
'class': 'logging.StreamHandler',
'formatter': 'console',
}
},
'root': {
'handlers': set(args.logging),
'level': 'INFO'
}
})
# Load config file
config = configuration.init(args.config)
from ip_control.rpc import RPC
import dns.resolver
import subprocess
import re
# Register signals
def reconfigure(_a, _b):
global rpc_instance, config
config = configuration.init(args.config)
rpc_instance.configure()
signal.signal(signal.SIGHUP, reconfigure)
class RequestHandler(SimpleJSONRPCRequestHandler):
def __init__(self, request, client_address, server):
global rpc_instance
rpc_instance.client_address, _ = client_address
SimpleJSONRPCRequestHandler.__init__(self, request, client_address, server)
def get_bind_info():
# Get bind information
try:
# Get FQDN
hostname = subprocess.check_output(['hostname', '-f']).strip()
# Resolve it
logging.info("Resolving %s.", hostname)
bind_ip = dns.resolver.query(hostname)[0].to_text()
except subprocess.CalledProcessError:
logging.error("Unable to retrieve router's hostname.")
return None
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
logging.error("Unable to resolve router's hostname.")
return None
logging.info("Binding to address %s.", bind_ip)
try:
control_domain = config.get('General', 'ip_control_dns_name')
# Get bind port
logging.info("Resolving %s TXT record.", control_domain)
bind_port = dns.resolver.query(control_domain, 'TXT')[0].to_text()
logging.info("Resolved to %s.", bind_port)
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
logging.error("Unable to resolve %s TXT record to fetch bind port.", control_domain)
return None
bind_port = re.search(r'\s?port=(\d+)', bind_port)
if not bind_port:
logging.error("Invalid TXT record for %s.", control_domain)
return None
else:
bind_port = int(bind_port.group(1))
logging.info("Binding to port %d.", bind_port)
return (bind_ip, bind_port)
# First, init dynamic routes
# Check for persistance (bootup or daemon restart)
persistance_file = config.get('General', 'persistance_file')
if not os.path.exists(persistance_file):
# Touch this file
try:
open(persistance_file, 'w')
except IOError:
logging.error("Cannot create persistance file.")
# Recreate dynamic files
open(config.get('General', 'bird4_dynamic_config'), 'w')
open(config.get('General', 'bird4_dynamic_routes'), 'w')
open(config.get('General', 'bird6_dynamic_config'), 'w')
open(config.get('General', 'bird6_dynamic_routes'), 'w')
# Setup our server
bind_info = None
while not bind_info:
try:
bind_info = get_bind_info()
except dns.resolver.Timeout:
logging.warning("Timeout occured when retrieving settings from DNS.")
except:
logging.warning("Unknown error occured when retrieving settings from DNS.")
if not bind_info:
import time
time.sleep(5)
rpc_instance = RPC(bind_info)
server = SimpleJSONRPCServer((rpc_instance.bind_ip, rpc_instance.bind_port),
requestHandler = RequestHandler)
server.register_instance(rpc_instance)
# Start it up
logging.info("Listening for requests.")
import select
while True:
try:
server.serve_forever()
except select.error:
# Just go along
pass