1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

samba-tool: add dns zoneoptions for aging control

This adds a subcommand for altering zone parameters.

At the moment the only options are related to record aging (a.k.a
scavenging). The code is structured to make it easy to add more
integer or boolean options, but it is not clear that this would be
useful; many other parameters are not used or would only have
deleterious effects.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>

Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Wed Apr 21 10:04:14 UTC 2021 on sn-devel-184
This commit is contained in:
Douglas Bagnall 2021-04-20 00:07:50 +12:00 committed by Andrew Bartlett
parent 38fe888f95
commit 0f29b8c2fe
2 changed files with 143 additions and 0 deletions

View File

@ -505,6 +505,94 @@ class cmd_serverinfo(Command):
print_serverinfo(self.outf, typeid, res)
def _add_integer_options(table, takes_options, integer_properties):
"""Generate options for cmd_zoneoptions"""
for k, doc, _min, _max in table:
o = '--' + k.lower()
opt = Option(o,
help=f"{doc} [{_min}-{_max}]",
type="int",
dest=k)
takes_options.append(opt)
integer_properties.append((k, _min, _max, o))
class cmd_zoneoptions(Command):
"""Change zone aging options."""
synopsis = '%prog <server> <zone> [options]'
takes_args = ['server', 'zone']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"versionopts": options.VersionOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option('--client-version', help='Client Version',
default='longhorn', metavar='w2k|dotnet|longhorn',
choices=['w2k', 'dotnet', 'longhorn'], dest='cli_ver'),
]
integer_properties = []
# Any zone parameter that is stored as an integer (which is most of
# them) can be added to this table. The name should be the dnsp
# mixed case name, which will get munged into a lowercase name for
# the option. (e.g. "Aging" becomes "--aging").
#
# Note: just because we add a name here doesn't mean we will use
# it.
_add_integer_options([
# ( name, help-string, min, max )
('Aging', 'Enable record aging', 0, 1),
('NoRefreshInterval',
'Aging no refresh interval in hours (0: use default)',
0, 10 * 365 * 24),
('RefreshInterval',
'Aging refresh interval in hours (0: use default)',
0, 10 * 365 * 24),
],
takes_options,
integer_properties)
def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
versionopts=None, **kwargs):
self.lp = sambaopts.get_loadparm()
self.creds = credopts.get_credentials(self.lp)
dns_conn = dns_connect(server, self.lp, self.creds)
client_version = dns_client_version(cli_ver)
nap_type = dnsserver.DNSSRV_TYPEID_NAME_AND_PARAM
for k, _min, _max, o in self.integer_properties:
if kwargs.get(k) is None:
continue
v = kwargs[k]
if _min is not None and v < _min:
raise CommandError(f"{o} must be at least {_min}")
if _max is not None and v > _max:
raise CommandError(f"{o} can't exceed {_max}")
name_param = dnsserver.DNS_RPC_NAME_AND_PARAM()
name_param.dwParam = v
name_param.pszNodeName = k
try:
dns_conn.DnssrvOperation2(client_version,
0,
server,
zone,
0,
'ResetDwordProperty',
nap_type,
name_param)
except WERRORError as e:
raise CommandError(f"Could not set {k} to {v}") from None
print(f"Set {k} to {v}", file=self.outf)
class cmd_zoneinfo(Command):
"""Query for zone information."""
@ -1065,6 +1153,7 @@ class cmd_dns(SuperCommand):
subcommands = {}
subcommands['serverinfo'] = cmd_serverinfo()
subcommands['zoneoptions'] = cmd_zoneoptions()
subcommands['zoneinfo'] = cmd_zoneinfo()
subcommands['zonelist'] = cmd_zonelist()
subcommands['zonecreate'] = cmd_zonecreate()

View File

@ -17,6 +17,7 @@
import os
import ldb
import re
from samba.auth import system_session
from samba.samdb import SamDB
@ -910,3 +911,56 @@ class DnsCmdTestCase(SambaToolCmdTest):
err,
"Failed to print zoneinfo")
self.assertTrue(out != '')
def test_zoneoptions(self):
for options, vals, error in (
(['--aging=1'], {'fAging': 'TRUE'}, False),
(['--aging=0'], {'fAging': 'FALSE'}, False),
(['--aging=-1'], {'fAging': 'FALSE'}, True),
(['--aging=2'], {}, True),
(['--aging=2', '--norefreshinterval=1'], {}, True),
(['--aging=1', '--norefreshinterval=1'],
{'fAging': 'TRUE', 'dwNoRefreshInterval': '1'}, False),
(['--aging=1', '--norefreshinterval=0'],
{'fAging': 'TRUE', 'dwNoRefreshInterval': '0'}, False),
(['--aging=0', '--norefreshinterval=99', '--refreshinterval=99'],
{'fAging': 'FALSE',
'dwNoRefreshInterval': '99',
'dwRefreshInterval': '99'}, False),
(['--aging=0', '--norefreshinterval=-99', '--refreshinterval=99'],
{}, True),
(['--refreshinterval=9999999'], {}, True),
(['--norefreshinterval=9999999'], {}, True),
):
result, out, err = self.runsubcmd("dns",
"zoneoptions",
os.environ["SERVER"],
self.zone,
self.creds_string,
*options)
if error:
self.assertCmdFail(result, "zoneoptions should fail")
else:
self.assertCmdSuccess(result,
out,
err,
"zoneoptions shouldn't fail")
info_r, info_out, info_err = self.runsubcmd("dns",
"zoneinfo",
os.environ["SERVER"],
self.zone,
self.creds_string)
self.assertCmdSuccess(info_r,
info_out,
info_err,
"zoneinfo shouldn't fail after zoneoptions")
info = {k: v for k, v in re.findall(r'^\s*(\w+)\s*:\s*(\w+)\s*$',
info_out,
re.MULTILINE)}
for k, v in vals.items():
self.assertIn(k, info)
self.assertEqual(v, info[k])