- DNSSEC
-- Logging
- More records
# PyNSC: Command-line interface
-# (c) 2024 Martin Mareš <mj@ucw.cz>
+# (c) 2024-2025 Martin Mareš <mj@ucw.cz>
import argparse
from argparse import Namespace
+import logging
from pathlib import Path
from texttable import Texttable
from nsconfig.core import Nsc, NscZonePrimary, NscZoneSecondary, NscZoneAlias
+logger = logging.getLogger(__name__)
+
def do_test(nsc: Nsc, args: Namespace) -> None:
test_dir = Path(args.output)
nsc.daemon.reload_daemon()
+class LogFormatter(logging.Formatter):
+
+ LOG_PREFIX = {
+ logging.WARNING: "WARNING",
+ logging.ERROR: "ERROR",
+ logging.CRITICAL: "FATAL",
+ }
+
+ def format(self, record):
+ out = super().format(record)
+ if record.levelno in LogFormatter.LOG_PREFIX:
+ out = LogFormatter.LOG_PREFIX[record.levelno] + ': ' + out
+ return out
+
+
+def setup_logging() -> None:
+ log_formatter = LogFormatter('%(message)s')
+
+ log_handler = logging.StreamHandler()
+ log_handler.setFormatter(log_formatter)
+ log_handler.setLevel(logging.INFO)
+
+ root_logger = logging.getLogger()
+ root_logger.addHandler(log_handler)
+ root_logger.setLevel(logging.INFO)
+
+
def main(nsc: Nsc) -> None:
parser = argparse.ArgumentParser(description='Configure name server')
subparsers = parser.add_subparsers(help='action to perform', dest='action', required=True, metavar='ACTION')
args = parser.parse_args()
+ setup_logging()
+
nsc.process()
if args.action == 'test':
# PyNSC: Main data structures
-# (c) 2024 Martin Mareš <mj@ucw.cz>
+# (c) 2024-2025 Martin Mareš <mj@ucw.cz>
from collections import defaultdict
from datetime import datetime, timedelta
import hashlib
from ipaddress import ip_address, IPv4Address, IPv6Address, ip_network, IPv4Network, IPv6Network
import json
+import logging
from pathlib import Path
import socket
import sys
if TYPE_CHECKING:
from nsconfig.daemon import NscDaemon
+logger = logging.getLogger(__name__)
+
class NscNode:
nsc_zone: 'NscZonePrimary'
else:
self.state.serial = prev + 1
if prev >= base + 99:
- print(f'WARNING: Serial number overflow for zone {self.name}, current is {self.state.serial}')
+ logger.warning(f'WARNING: Serial number overflow for zone {self.name}, current is {self.state.serial}')
def process(self) -> None:
if self.config.add_null_mx:
# PyNSC: Generic interface for generating daemon configuration
-# (c) 2024 Martin Mareš <mj@ucw.cz>
+# (c) 2024-2025 Martin Mareš <mj@ucw.cz>
-from io import StringIO
+import logging
from pathlib import Path
import subprocess
import sys
DaemonConfig = List[Tuple[str, List[str]]]
+logger = logging.getLogger(__name__)
+
class NscDaemon:
nsc: Nsc
changed = True
if changed:
- print('Wrote new daemon configuration')
+ logger.info('Wrote new daemon configuration')
else:
- print('Daemon configuration not changed')
+ logger.info('Daemon configuration not changed')
return changed
def _run_command(self, argv, **kwargs) -> None:
res = subprocess.run(argv, **kwargs)
if res.returncode > 0:
- print(f'Command failed: {argv}')
+ logger.error(f'Command failed: {argv}')
sys.exit(1)
# PyNSC: Generator of configuration for BIND 9
-# (c) 2024 Martin Mareš <mj@ucw.cz>
+# (c) 2024-2025 Martin Mareš <mj@ucw.cz>
+import logging
from pathlib import Path
from typing import List
from nsconfig.daemon import NscDaemon, DaemonConfig
+logger = logging.getLogger(__name__)
+
+
class NscDaemonBind(NscDaemon):
config_dir_path: Path
config_file: str
def reload_zone(self, z: NscZone) -> None:
if (isinstance(z, NscZonePrimary) or isinstance(z, NscZoneAlias)) and not self.need_full_reload:
- print(f'Reloading zone {z.name}')
+ logger.info(f'Reloading zone {z.name}')
self._run_command([self.control_command, 'reload', z.name])
def reload_daemon(self) -> None:
if self.need_full_reload:
- print('Reloading daemon')
+ logger.info('Reloading daemon')
self._run_command([self.control_command, 'reload'])