mirror of
https://github.com/xcat2/confluent.git
synced 2024-11-22 17:43:14 +00:00
219ad8f56b
python2 compatibility and various scenarios not handled.
161 lines
5.4 KiB
Python
161 lines
5.4 KiB
Python
#!/usr/bin/python2
|
|
import argparse
|
|
import os
|
|
import signal
|
|
import sys
|
|
try:
|
|
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
|
except AttributeError:
|
|
pass
|
|
|
|
path = os.path.dirname(os.path.realpath(__file__))
|
|
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
|
|
if path.startswith('/opt'):
|
|
sys.path.append(path)
|
|
import confluent.client as client
|
|
import confluent.sortutil as sortutil
|
|
|
|
def partitionhostsline(line):
|
|
comment = ''
|
|
if '#' in line:
|
|
cmdidx = line.index('#')
|
|
comment = line[cmdidx:]
|
|
line = line[:cmdidx].strip()
|
|
if not line.strip():
|
|
return '', [], comment
|
|
ipaddr, names = line.split(None, 1)
|
|
names = names.split()
|
|
return ipaddr, names, comment
|
|
|
|
class HostMerger(object):
|
|
def __init__(self):
|
|
self.byip = {}
|
|
self.byname = {}
|
|
self.byname6 = {}
|
|
self.sourcelines = []
|
|
self.targlines = []
|
|
|
|
def read_source(self, sourcefile):
|
|
with open(sourcefile, 'r') as hfile:
|
|
self.sourcelines = hfile.read().split('\n')
|
|
while not self.sourcelines[-1]:
|
|
self.sourcelines = self.sourcelines[:-1]
|
|
for x in range(len(self.sourcelines)):
|
|
line = self.sourcelines[x]
|
|
currip, names, comment = partitionhostsline(line)
|
|
if currip:
|
|
self.byip[currip] = x
|
|
byname = self.byname
|
|
if ':' in currip:
|
|
byname = self.byname6
|
|
for name in names:
|
|
byname[name] = x
|
|
|
|
def add_entry(self, ip, names):
|
|
targ = self.byname
|
|
if ':' in ip:
|
|
targ = self.byname6
|
|
line = '{:<39} {}'.format(ip, names)
|
|
x = len(self.sourcelines)
|
|
self.sourcelines.append(line)
|
|
for name in names.split():
|
|
if not name:
|
|
continue
|
|
targ[name] = x
|
|
self.byip[ip] = x
|
|
|
|
|
|
def read_target(self, targetfile):
|
|
if not os.path.exists(targetfile):
|
|
return
|
|
with open(targetfile, 'r') as hfile:
|
|
lines = hfile.read().split('\n')
|
|
while lines and not lines[-1]:
|
|
lines = lines[:-1]
|
|
for y in range(len(lines)):
|
|
line = lines[y]
|
|
currip, names, comment = partitionhostsline(line)
|
|
byname = self.byname
|
|
if ':' in currip:
|
|
byname = self.byname6
|
|
if currip in self.byip:
|
|
x = self.byip[currip]
|
|
if self.sourcelines[x] is None:
|
|
# have already consumed this entry
|
|
continue
|
|
self.targlines.append(self.sourcelines[x])
|
|
self.sourcelines[x] = None
|
|
continue
|
|
for name in names:
|
|
if name in byname:
|
|
x = byname[name]
|
|
if self.sourcelines[x] is None:
|
|
break
|
|
self.targlines.append(self.sourcelines[x])
|
|
self.sourcelines[x] = None
|
|
break
|
|
else:
|
|
self.targlines.append(line)
|
|
|
|
def write_out(self, targetfile):
|
|
while self.targlines and not self.targlines[-1]:
|
|
self.targlines = self.targlines[:-1]
|
|
while self.sourcelines and not self.sourcelines[-1]:
|
|
self.sourcelines = self.sourcelines[:-1]
|
|
if not self.sourcelines:
|
|
break
|
|
with open(targetfile, 'w') as hosts:
|
|
for line in self.targlines:
|
|
hosts.write(line + '\n')
|
|
for line in self.sourcelines:
|
|
if line is not None:
|
|
hosts.write(line + '\n')
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser(description="Create/amend /etc/hosts file for given noderange")
|
|
ap.add_argument('noderange', help='Noderange to generate/update /etc/hosts for')
|
|
ap.add_argument('-i', '--ip', help='Expression to generate addresses (e.g. 172.16.1.{n1} or fd2b:246f:8a50::{n1:x})')
|
|
ap.add_argument('-n', '--name', help='Expression for name to add ({node}-compute, etc). If unspecified, "{node} {node}.{dns.domain}" will be used', action='append')
|
|
args = ap.parse_args()
|
|
c = client.Command()
|
|
if args.name:
|
|
names = ' '.join(args.name)
|
|
else:
|
|
names = '{node} {node}.{dns.domain}'
|
|
if not args.ip:
|
|
sys.stderr.write('-i is currently required\n')
|
|
sys.exit(1)
|
|
namesbynode = {}
|
|
ipbynode = {}
|
|
expurl = '/noderange/{0}/attributes/expression'.format(args.noderange)
|
|
expression = names
|
|
exitcode = 0
|
|
exitcode |= expand_expression(c, namesbynode, expurl, names)
|
|
exitcode |= expand_expression(c, ipbynode, expurl, args.ip)
|
|
if exitcode:
|
|
sys.exit(exitcode)
|
|
merger = HostMerger()
|
|
for node in ipbynode:
|
|
merger.add_entry(ipbynode[node], namesbynode[node])
|
|
if os.path.exists('/etc/hosts'):
|
|
merger.read_target('/etc/hosts')
|
|
os.rename('/etc/hosts', '/etc/hosts.confluentbkup')
|
|
merger.write_out('/etc/hosts')
|
|
|
|
|
|
|
|
def expand_expression(c, namesbynode, expurl, expression):
|
|
exitcode = 0
|
|
for exp in c.create(expurl, {'expression': expression}):
|
|
if 'error' in exp:
|
|
sys.stderr.write(exp['error'] + '\n')
|
|
exitcode |= exp.get('errorcode', 1)
|
|
ex = exp.get('databynode', ())
|
|
for node in ex:
|
|
namesbynode[node] = ex[node]['value']
|
|
return exitcode
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|