/usr/lib/python3/dist-packages/provisioningserver/dns/actions.py is in python3-maas-provisioningserver 2.0.0~beta3+bzr4941-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | # Copyright 2014-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Low-level actions to manage the DNS service, like reloading zones."""
__all__ = [
"bind_reconfigure",
"bind_reload",
"bind_reload_zones",
"bind_write_configuration",
"bind_write_options",
"bind_write_zones",
]
import collections
from subprocess import CalledProcessError
from time import sleep
from provisioningserver.dns.config import (
DNSConfig,
execute_rndc_command,
set_up_options_conf,
)
from provisioningserver.logger import get_maas_logger
from provisioningserver.utils.shell import ExternalProcessError
maaslog = get_maas_logger("dns")
def bind_reconfigure():
"""Ask BIND to reload its configuration and *new* zone files.
From rndc(8):
Reload the configuration file and load new zones, but do not reload
existing zone files even if they have changed. This is faster than a
full reload when there is a large number of zones because it avoids the
need to examine the modification times of the zones files.
"""
try:
execute_rndc_command(("reconfig",))
except CalledProcessError as exc:
maaslog.error("Reloading BIND configuration failed: %s", exc)
# Log before upgrade so that the output does not go to maaslog.
ExternalProcessError.upgrade(exc)
raise
def bind_reload():
"""Ask BIND to reload its configuration and all zone files. This operation
is 'best effort' (with logging) as the server may not be running, and there
is often no context for reporting.
:return: True if success, False otherwise.
"""
try:
execute_rndc_command(("reload",))
return True
except CalledProcessError as exc:
maaslog.error("Reloading BIND failed (is it running?): %s", exc)
return False
def bind_reload_with_retries(attempts=10, interval=2):
"""Ask BIND to reload its configuration and all zone files.
:param attempts: The number of attempts.
:param interval: The time in seconds to sleep between each attempt.
"""
for countdown in range(attempts - 1, -1, -1):
if bind_reload():
break
if countdown == 0:
break
else:
sleep(interval)
def bind_reload_zones(zone_list):
"""Ask BIND to reload the zone file for the given zone.
:param zone_list: A list of zone names to reload, or a single name as a
string.
:return: True if success, False otherwise.
"""
ret = True
if not isinstance(zone_list, list):
zone_list = [zone_list]
for name in zone_list:
try:
execute_rndc_command(("reload", name))
except CalledProcessError as exc:
maaslog.error(
"Reloading BIND zone %r failed (is it running?): %s",
name,
exc)
ret = False
return ret
def bind_write_configuration(zones, trusted_networks):
"""Write BIND's configuration.
:param zones: Those zones to include in main config.
:type zones: Sequence of :py:class:`DomainData`.
:param trusted_networks: A sequence of CIDR network specifications that
are permitted to use the DNS server as a forwarder.
"""
# trusted_networks was formerly specified as a single IP address with
# netmask. These assertions are here to prevent code that assumes that
# slipping through.
assert not isinstance(trusted_networks, (bytes, str))
assert isinstance(trusted_networks, collections.Sequence)
dns_config = DNSConfig(zones=zones)
dns_config.write_config(trusted_networks=trusted_networks)
def bind_write_options(upstream_dns, dnssec_validation):
"""Write BIND options.
:param upstream_dns: A sequence of upstream DNS servers.
"""
# upstream_dns was formerly specified as a single IP address. These
# assertions are here to prevent code that assumes that slipping through.
assert not isinstance(upstream_dns, (bytes, str))
assert isinstance(upstream_dns, collections.Sequence)
set_up_options_conf(
upstream_dns=upstream_dns, dnssec_validation=dnssec_validation)
def bind_write_zones(zones):
"""Write out DNS zones.
:param zones: Those zones to write.
:type zones: Sequence of :py:class:`DomainData`.
"""
for zone in zones:
zone.write_config()
|