Skip to content

Fix NTP/SNMP/probe config on NAPALM proxy minions (bare-name templates)#69793

Open
ggiesen wants to merge 4 commits into
saltstack:3006.xfrom
ggiesen:fix-napalm-template-family
Open

Fix NTP/SNMP/probe config on NAPALM proxy minions (bare-name templates)#69793
ggiesen wants to merge 4 commits into
saltstack:3006.xfrom
ggiesen:fix-napalm-template-family

Conversation

@ggiesen

@ggiesen ggiesen commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Restores NTP / SNMP / RPM-probe configuration on NAPALM (proxy) minions, broken
the same way #62170 broke user management.

napalm_ntp (set_peers, set_servers, delete_peers, delete_servers),
napalm_snmp (update_config, remove_config) and napalm_probes
(set_probes, delete_probes, schedule_probes) all call net.load_template
with a bare template name (e.g. "set_ntp_peers"). net.load_template used
to route bare names into NAPALM's own renderer, but that path was removed in the
Sodium release (#57370) -- whose own deprecation warning explicitly said
netntp/netsnmp/netusers users could ignore it. The bare name now falls
through to the fileserver as Local file source set_ntp_peers does not exist,
so every one of these config functions (and the netntp/netsnmp states on top
of them) fails.

This lifts the resolver introduced for users in #62170 into a shared
salt.utils.napalm.template_path, which resolves the driver's NAPALM-shipped
template (set_ntp_peers.j2 etc., searched along the driver class MRO) to an
absolute path so the still-supported Salt rendering pipeline renders it. The
three modules pass that absolute path to net.load_template, or return a clear
salt.utils.napalm.template_not_available message when the driver ships no such
template.

What issues does this PR fix or reference?

Same root cause as #62170 (which fixes the netusers half). napalm_users is
intentionally left to #62170 here; once both land, a follow-up dedups its local
resolver onto the shared one.

Validation on real hardware

Reproduced the failure, then validated against a live Juniper EX3400
(Junos 23.4R2) over NETCONF driving a real napalm/junos proxy (onedir
3006.x):

  • ntp.set_servers 192.0.2.10 test=True -> before: Local file source set_ntp_servers does not exist; after: a proper diff (+ server 192.0.2.10;).
    Committed for real, confirmed present in show configuration system ntp, then
    removed again with ntp.delete_servers.

Known limitation (upstream NAPALM, not this PR)

NAPALM's junos snmp_config.j2 / delete_snmp_config.j2 / set_probes.j2 /
delete_probes.j2 templates still use Python-2 dict.iteritems(), so they do
not render under Python 3 regardless of how they are reached -- these functions
route correctly now but need NAPALM to modernize those templates upstream (I can
follow up in the NAPALM repo). The NTP templates and schedule_probes.j2 are
py3-clean, which is why NTP works end to end above. Fixing the Salt-side routing
is still correct and necessary: it turns a misleading "file source does not
exist" error into an honest render path.

Merge requirements satisfied?

  • Docs
  • Changelog
  • Tests written/updated

New tests/pytests/unit/utils/test_napalm.py covers the shared resolver (MRO
fall-through to a base-class template, object -> exception skip, missing ->
None, and the failure-dict shape). test_ntp.py / test_snmp.py are rewritten
and test_probes.py added with real routing tests: each of the 9 functions is
asserted to request the correct template name, pass the resolved absolute
path (not the bare name), forward test/commit/inherit_napalm_device, and
return a clear error when the driver ships no template. All fail against the
current code; the resolver and routing tests are mutation-checked (a set/delete
name swap or a collapsed MRO walk makes them fail).

Commits signed with GPG?

No

napalm_ntp (set_peers/set_servers/delete_peers/delete_servers), napalm_snmp
(update_config/remove_config) and napalm_probes (set_probes/delete_probes/
schedule_probes) all call net.load_template with a bare template name (e.g.
"set_ntp_peers"). net.load_template used to route bare names into NAPALM's own
renderer, but that path was removed in the Sodium release (saltstack#57370) -- whose own
deprecation warning explicitly told netntp/netsnmp/netusers users to ignore it.
The bare name now falls through to the fileserver as "Local file source
set_ntp_peers does not exist", so every one of these functions fails.

Lift the resolver introduced for users in saltstack#62170 into a shared
salt.utils.napalm.template_path (walks the driver class MRO + inspect.getfile,
catching TypeError/OSError, returns None when the driver ships no such template)
plus salt.utils.napalm.template_not_available (standard failure payload). The
three modules resolve the driver's NAPALM-shipped template to an absolute path
and render it through the Salt pipeline, or return the clear failure message.
template_not_available also closes the per-call connection a non-always-alive
proxy/minion opened, since it short-circuits net.load_template (which would
otherwise close it).

napalm_users is intentionally left to saltstack#62170; a follow-up dedups its local
resolver onto the shared one.

Validated on a live Juniper EX3400 (Junos 23.4R2): ntp.set_servers renders,
commits, is confirmed in the device config, and is removed again. (NAPALM's
junos snmp/probes templates still use py2 dict.iteritems() and need modernizing
upstream in NAPALM; the NTP templates are py3-clean.)

New tests/pytests/unit/utils/test_napalm.py covers the resolver (MRO
concrete-over-base precedence, base fall-through, OSError/TypeError skip, missing
-> None) and the close behaviour; test_ntp/test_snmp are rewritten and
test_probes added with routing tests asserting the correct template name, the
resolved path, forwarded flags, and inherit_napalm_device identity.
@ggiesen

ggiesen commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Filed the upstream NAPALM template fix referenced above: napalm-automation/napalm#2326. It replaces the Python-2 dict.iteritems() in the snmp_config/delete_snmp_config/set_probes/delete_probes/schedule_probes templates across all six drivers (and fixes a separate mis-nested delete_users template on nxos/nxos_ssh), so once it lands the SNMP and probe paths this PR wires up render on Python 3. NTP already works end to end.

napalm_probes.set_probes/delete_probes/schedule_probes now resolve the driver's
template and no longer return result=True for the bare-name mock, so the legacy
unittest-style tests (which asserted the pre-fix behaviour) fail. They are
superseded by tests/pytests/unit/modules/napalm/test_probes.py added here, which
covers config/results plus the routing and no-template paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants