mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +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:
parent
38fe888f95
commit
0f29b8c2fe
@ -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()
|
||||
|
@ -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])
|
||||
|
Loading…
Reference in New Issue
Block a user