NetAuto Academy

Nornir for Network Engineers

nornir_netmiko: Wrapping Netmiko as a Task Plugin

Advanced13 min read

What you'll learn

  • That nornir_netmiko is a plugin wrapping the Netmiko already learned, not a new tool
  • The real signatures of netmiko_send_command and netmiko_send_config
  • How a real, unreachable device's failure surfaces through a Nornir task
  • Where this fits: Option A for this module's capstone
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

The same Netmiko, a different caller

Not a new tool

ConnectHandler, send_command, send_config_set, and Netmiko's own exceptions were fully taught in Netmiko Fundamentals (Phase 2.7) — none of that is repeated here. nornir_netmiko is a plugin: it calls the exact Netmiko you already know, from inside a Nornir task, so a task function doesn't need to manage ConnectHandler itself.

  1. nr.run(task=netmiko_send_command, ...)a Nornir task
  2. nornir_netmikothe plugin
  3. Netmiko's ConnectHandler / send_commandexactly what Phase 2.7 taught
  4. A real device (or none)
Quick checkConcept check
What does nornir_netmiko actually add on top of Netmiko itself?

The real, verified signatures

netmiko_send_command's real signature, installed nornir-netmiko 1.0.1
def netmiko_send_command(
  task: Task,
  command_string: str,
  use_timing: bool = False,
  enable: bool = False,
  **kwargs: Any,
) -> Result:
  """Execute Netmiko's send_command (or send_command_timing)."""

Verified directly by inspecting the installed package, not assumed from memory. command_string is the show command; **kwargs pass through to Netmiko's own send_command() call.

using it
from nornir_netmiko import netmiko_send_command

agg = nr.run(task=netmiko_send_command, command_string="show version")

No ConnectHandler, no manual connection management — nr.run() handles calling the task once per host in the (filtered or full) inventory.

Quick checkIdentify the correct code
Which correctly runs a show command across the inventory using nornir_netmiko?

Real failure behavior, verified against an unreachable target

verify_real_failure.py
one = nr.filter(name="SW1")
# one inherits the username/password already injected onto
# nr.inventory.defaults via Lesson 2's os.environ pattern -- filtering
# never requires re-injecting credentials, verified directly.

result = one.run(task=netmiko_send_command, command_string="show version")

print("agg.failed:", result.failed)
for hostname, multi_result in result.items():
  print(hostname, "failed:", multi_result.failed)
  print(hostname, "exception:", repr(multi_result[0].exception))

Run against SW1's inventory IP (10.10.10.1), which nothing is listening on in this environment -- a genuine, reproducible failure, not a hypothetical. Credentials still come from Lesson 2's environment-variable injection, never hardcoded here.

output — real, verified
agg.failed: True
SW1 failed: True
SW1 exception: NetmikoTimeoutException('TCP connection to device failed.\n\nCommon causes of this problem are:\n1. Incorrect hostname or IP address.\n2. Wrong TCP port.\n3. Intermediate firewall blocking access.\n\nDevice settings: cisco_ios 10.10.10.1:22\n\n')

Real, verified output -- the exact NetmikoTimeoutException message already verified in Phase 2.7, now surfaced as multi_result[0].exception through a Nornir task instead of a bare try/except block.

Quick checkPredict output
Where does a NetmikoTimeoutException raised inside netmiko_send_command actually end up, from the caller's perspective?

A real, useful extra: netmiko_send_config's built-in dry_run

netmiko_send_config's real signature, installed nornir-netmiko 1.0.1
def netmiko_send_config(
  task: Task,
  config_commands: list[str] | None = None,
  config_file: str | None = None,
  enable: bool = True,
  dry_run: bool | None = None,
  **kwargs: Any,
) -> Result:

Verified directly. dry_run is a real, built-in parameter -- the same safety concept Reliable Automation taught by hand (Phase 2.8), now offered by the plugin itself rather than something you implement yourself.

Quick checkScenario
Why is netmiko_send_config's built-in dry_run parameter worth noting, given what Reliable Automation already taught?

Key takeaways

  • nornir_netmiko wraps the exact Netmiko already taught in Phase 2.7 — ConnectHandler, send_command, and Netmiko's exceptions are not re-taught here.
  • netmiko_send_command(task, command_string, ...) and netmiko_send_config(task, config_commands, ..., dry_run=...) — real, verified signatures from the installed package, not assumed.
  • A real, unreachable target's NetmikoTimeoutException was verified directly, ending up on multi_result[0].exception — the same exception Phase 2.7 verified, now surfaced through Nornir's own result model.
  • netmiko_send_config's built-in dry_run parameter is the same safety principle Reliable Automation taught by hand, now offered by the plugin itself.