NetAuto Academy

Multi-vendor Automation

Running Normalized Getters Across a Mixed Fleet with napalm_get

Advanced14 min read

What you'll learn

  • napalm_get's real, verified signature and batched-getter behavior
  • How napalm_get's result differs in shape from nornir_netmiko's per-command tasks
  • A real, executed multi-vendor-shaped run: three successes, one failure
  • Why only get_facts/get_interfaces are used here, not a wider catalog of getters
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

napalm_get: real signature, a real architectural difference

napalm_get's real signature, installed nornir_napalm 0.6.0
def napalm_get(
  task: Task,
  getters: List[str],
  getters_options: Dict[str, Dict[str, Any]] | None = None,
  **kwargs: Any,
) -> Result: ...

Verified directly via inspect.signature. getters is a LIST of getter names -- one task call can request multiple getters at once.

A real difference from nornir_netmiko, not assumed to be the same

nornir_netmiko (Phase 3.4) is one task per command: netmiko_send_command(command_string='show version'). napalm_get batches multiple getters into ONE task call: napalm_get(getters=['get_facts', 'get_interfaces']). This was verified directly from the real signature and confirmed by execution below -- not assumed to mirror nornir_netmiko's shape.

Quick checkConcept check
How does napalm_get's real signature differ architecturally from nornir_netmiko's netmiko_send_command?

A real, verified 4-host run

verify_multivendor_get.py
from nornir import InitNornir
from nornir_napalm.plugins.tasks import napalm_get

nr = InitNornir(
  inventory={"plugin": "SimpleInventory", "options": {
      "host_file": "inventory/hosts.yaml",
      "group_file": "inventory/groups.yaml",
      "defaults_file": "inventory/defaults.yaml",
  }},
)
agg = nr.run(task=napalm_get, getters=["get_facts", "get_interfaces"])

One task call, across SW1 (Cisco-like), SW2 (Arista-like), SW3 (Juniper-like), and SW4 (unreachable) -- the same 4-host inventory from Lesson 2, plus SW4 (Lesson 4 introduces its fail_on_open setup).

output — real, verified
agg.failed: True

SW1 (vendor_label=Cisco-like): failed=False
facts.vendor: Cisco   facts.hostname: SW1   interface_list: ['GigabitEthernet0/1']
get_interfaces: {'GigabitEthernet0/1': {'is_up': True, ..., 'description': 'mgmt-uplink'}}

SW2 (vendor_label=Arista-like): failed=False
facts.vendor: Arista   facts.hostname: SW2   interface_list: ['Ethernet1']
get_interfaces: {'Ethernet1': {'is_up': True, ..., 'description': 'mgmt-uplink'}}

SW3 (vendor_label=Juniper-like): failed=False
facts.vendor: Juniper   facts.hostname: SW3   interface_list: ['ge-0/0/0']
get_interfaces: {'ge-0/0/0': {'is_up': True, ..., 'description': 'uplink'}}

SW4 (vendor_label=Cisco-like): failed=True
exception: ConnectionException('You told me to do this')

Real, verified output. The exact same task call and getters list produced correctly-shaped results from three different fixture-driven 'vendors' and cleanly isolated SW4's failure -- no per-vendor branching written anywhere in the calling code.

Quick checkIdentify the correct code
Given the real output above, which correctly reads SW2's get_interfaces result from the AggregatedResult?
Quick checkPredict output
SW1 and SW2's get_interfaces both show description: 'mgmt-uplink', but SW3 shows description: 'uplink'. What does this demonstrate?

Getter scope: two, deliberately, not a catalog

Why only get_facts and get_interfaces

NAPALM has more getters -- get_environment(), get_bgp_neighbors(), and others, real and confirmed to exist. This module deliberately uses only get_facts and get_interfaces, the two shapes already taught in full in NAPALM Lesson 3. The goal here is demonstrating napalm_get's batching and multi-vendor behavior, not touring every getter NAPALM offers.

Quick checkScenario
Why does this lesson reuse get_facts/get_interfaces instead of introducing get_environment() or get_bgp_neighbors()?

Key takeaways

  • napalm_get(task, getters=[...]) batches multiple getters into one task call -- a real, verified architectural difference from nornir_netmiko's one-task-per-command pattern.
  • A real, 4-host run confirmed: the exact same task call correctly resolved three different mock-driven 'vendors' plus one real, isolated failure -- no per-vendor code written by the caller.
  • Result.result from napalm_get is a dict keyed by getter name -- verified directly, not assumed to mirror any other task's shape.
  • This lesson deliberately reuses only get_facts/get_interfaces -- NAPALM's wider getter catalog stays out of scope, keeping the focus on integration, not enumeration.