#!/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()