134 lines
5.1 KiB
Python
Executable File
134 lines
5.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import dns.rdataclass
|
|
import dns.rdataset
|
|
import dns.rdatatype
|
|
import dnsmgr
|
|
import sys
|
|
|
|
from time import sleep
|
|
|
|
|
|
def main():
|
|
preparser = argparse.ArgumentParser(add_help=False)
|
|
preparser.add_argument('-b', '--batch', action='store_true')
|
|
preargs, args = preparser.parse_known_args()
|
|
nargs = None if preargs.batch else '?'
|
|
|
|
parser = argparse.ArgumentParser(description='Add DNS zones.')
|
|
parser.add_argument('-b', '--batch', help='run in batch mode (no user input)', action='store_true')
|
|
parser.add_argument('-c', '--config', help='path to config file', default=dnsmgr.DEFAULT_CFGFILE)
|
|
parser.add_argument('-t', '--config-template', help='config file/template (overrides value set in ZONE_TEMPLATES config option)', default=None)
|
|
parser.add_argument('-z', '--zone-template', help='zone file/template (overrides value set in ZONE_TEMPLATES config option)', default=None)
|
|
parser.add_argument('zone', metavar='ZONE[@VIEWS]', nargs=nargs, help='DNS zone name and optional list of views (comma separated or asterisk to select all views)', default=None)
|
|
args = parser.parse_args()
|
|
|
|
try:
|
|
manager = dnsmgr.DNSManager(cfgfile=args.config)
|
|
except RuntimeError as e:
|
|
dnsmgr.printe(f'config: {e}')
|
|
sys.exit(100)
|
|
|
|
managed_views = sorted(manager.config.zones_config.keys())
|
|
|
|
try:
|
|
if args.zone is None:
|
|
name = dnsmgr.input_name()
|
|
rows = [[view] for view in managed_views]
|
|
index = dnsmgr.prettyselect(['View'], rows, prompt='Select view', also_valid=['*'])
|
|
views = managed_views if index == '*' else [managed_views[index]]
|
|
else:
|
|
(name, views) = dnsmgr.name_views_from_text(args.zone)
|
|
if views is None:
|
|
if len(managed_views) > 1:
|
|
raise RuntimeError('multiple managed views configured but none specified')
|
|
elif managed_views[0] != dnsmgr.NAMED_DEFAULT_VIEW:
|
|
raise RuntimeError('the default view is not managed')
|
|
views = managed_views
|
|
elif views == '*':
|
|
views = managed_views
|
|
else:
|
|
for view in views:
|
|
if view not in managed_views:
|
|
raise RuntimeError(f'managed view does not exist -- \'{view}\'')
|
|
|
|
existing_views = [zone.view for zone in filter(lambda zone: zone.origin == name and zone.view in views, manager.all_zones)]
|
|
if existing_views:
|
|
views = 'and '.join(existing_views)
|
|
raise RuntimeError(f'zone already exists in view {views}')
|
|
|
|
except RuntimeError as e:
|
|
dnsmgr.printe(e)
|
|
sys.exit(150)
|
|
except KeyboardInterrupt:
|
|
sys.exit(0)
|
|
|
|
if not args.batch:
|
|
for view in views:
|
|
origin = name.to_text(omit_final_dot=True)
|
|
print(f'View: {view}')
|
|
print(f'\033[32m+ {origin}\033[0m\n')
|
|
|
|
if not dnsmgr.input_yes_no():
|
|
sys.exit(0)
|
|
|
|
zones = []
|
|
for view in views:
|
|
origin = name.to_text(omit_final_dot=True)
|
|
if len(views) > 1 or view != dnsmgr.NAMED_DEFAULT_VIEW:
|
|
origin = f'{origin}@{view}'
|
|
print(f"Adding zone '{origin}'... ", end='')
|
|
|
|
try:
|
|
zone = manager.add_zone(name, view, args.config_template, args.zone_template)
|
|
manager.generate_config(view)
|
|
print('OK')
|
|
if manager.config.zones_config[view].catalog_zone:
|
|
zones.append(zone)
|
|
except RuntimeError as e:
|
|
dnsmgr.printe(e)
|
|
sys.exit(160)
|
|
|
|
try:
|
|
print('Reloading named... ', end='')
|
|
manager.named_reload()
|
|
print('OK')
|
|
except RuntimeError as e:
|
|
dnsmgr.printe(e)
|
|
sys.exit(170)
|
|
|
|
if zones:
|
|
sleep(2)
|
|
|
|
for zone in zones:
|
|
catalog_zone_name = manager.config.zones_config[zone.view].catalog_zone
|
|
try:
|
|
catalog_zones = manager.get_zones(catalog_zone_name, all_zones=True)
|
|
except RuntimeError as e:
|
|
raise RuntimeError(f'catalog zone of view \'{zone.view}\': {e}')
|
|
|
|
origin = zone.origin.to_text(omit_final_dot=True)
|
|
if len(zones) > 1 or zone.view != dnsmgr.NAMED_DEFAULT_VIEW:
|
|
origin = f'{origin}@{zone.view}'
|
|
|
|
for catalog_zone in catalog_zones:
|
|
rdata = dnsmgr.rdata_from_text(dns.rdatatype.PTR, zone.origin.to_text(), catalog_zone.origin)
|
|
rdataset = dns.rdataset.Rdataset(dns.rdataclass.IN, dns.rdatatype.PTR, ttl=3600)
|
|
rdataset.add(rdata)
|
|
rdname = dns.name.from_text(zone.nfz() + '.zones', catalog_zone.origin)
|
|
catalog_zone_origin = catalog_zone.origin.to_text(omit_final_dot=True)
|
|
if catalog_zone.view != dnsmgr.NAMED_DEFAULT_VIEW:
|
|
catalog_zone_origin += f'@{catalog_zone.view}'
|
|
|
|
try:
|
|
print(f'Adding zone \'{origin}\' to catalog zone \'{catalog_zone_origin}\'... ', end='')
|
|
manager.add_zone_record(catalog_zone, rdname, rdataset)
|
|
print('OK')
|
|
except RuntimeError as e:
|
|
dnsmgr.printe(e)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|