NetAuto Academy

NAPALM for Network Engineers

Drivers and Connecting: get_network_driver()

Advanced13 min read

What you'll learn

  • get_network_driver()'s real signature and behavior
  • A driver's real constructor and connection lifecycle
  • That NAPALM's IOS driver wraps the exact Netmiko already known, verified from source
  • A real connection failure against an unreachable address
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

One function, many vendors

get_network_driver's real signature, installed napalm 5.2.0
def get_network_driver(name: str, prepend: bool = True) -> Type[NetworkDriver]:
  """Searches for a class derived from NetworkDriver for the given vendor name."""

Verified directly by inspecting the installed package, not assumed from memory. name selects the vendor -- 'ios', 'eos', 'junos', and others.

real, verified drivers -- each imported successfully
from napalm import get_network_driver

for name in ["ios", "eos", "junos", "nxos", "nxos_ssh", "iosxr", "mock"]:
  print(name, "->", get_network_driver(name))

Every name below was actually imported, not assumed to exist.

output — real, verified
ios -> <class 'napalm.ios.ios.IOSDriver'>
eos -> <class 'napalm.eos.eos.EOSDriver'>
junos -> <class 'napalm.junos.junos.JunOSDriver'>
nxos -> <class 'napalm.nxos.nxos.NXOSDriver'>
nxos_ssh -> <class 'napalm.nxos_ssh.nxos_ssh.NXOSSSHDriver'>
iosxr -> <class 'napalm.iosxr.iosxr.IOSXRDriver'>
mock -> <class 'napalm.base.mock.MockDriver'>

A single pip install napalm bundles all of these -- no separate per-vendor package needed, verified directly against the installed package's dependency list.

Quick checkConcept check
What does get_network_driver('ios') actually return?

A driver's real constructor

IOSDriver's real constructor, installed napalm 5.2.0
def __init__(self, hostname, username, password, timeout=60, optional_args=None):
  ...

Verified via inspect.signature. Every driver across every vendor shares this same constructor shape -- hostname/username/password, with optional_args for vendor-specific tuning.

Credentials never as string literals

As with every prior module, username/password come from environment variables at runtime, never hardcoded — os.environ.get("NAPALM_USERNAME", ""), not a literal string sitting in a script or committed anywhere.

instantiating (not yet connecting)
import os
from napalm import get_network_driver

driver_cls = get_network_driver("ios")
driver = driver_cls(
  hostname="10.10.10.1",
  username=os.environ.get("NAPALM_USERNAME", ""),
  password=os.environ.get("NAPALM_PASSWORD", ""),
  timeout=10,
)

Instantiating a driver does not connect to anything yet -- exactly like Netmiko's ConnectHandler being separate from an open connection.

Quick checkIdentify the correct code
Which correctly builds an IOS driver instance with credentials from the environment?

open(), close(), and a real discovery: it wraps Netmiko

IOSDriver.open — real source, installed napalm 5.2.0
def open(self):
  """Open a connection to the device."""
  device_type = "cisco_ios"
  if self.transport == "telnet":
      device_type = "cisco_ios_telnet"
  self.device = self._netmiko_open(
      device_type, netmiko_optional_args=self.netmiko_optional_args
  )

A genuine, source-verified discovery: NAPALM's IOS driver does not reimplement SSH handling -- open() literally delegates to Netmiko internally, using the exact same 'cisco_ios' device_type this curriculum has used since Phase 2.7.

Quick checkScenario
Given IOSDriver.open()'s real source above, what is NAPALM's IOS driver actually doing under the hood when you call driver.open()?

A real connection failure

verify_real_ios_failure.py
import time
driver = driver_cls  # from above, hostname="10.10.10.1"
start = time.time()
try:
  driver.open()
except Exception as e:
  print("elapsed:", round(time.time() - start, 2), "s")
  print(type(e).__module__ + "." + type(e).__name__, "->", repr(e))

Run against 10.10.10.1, which nothing is listening on in this environment -- a genuine, reproducible failure, not a hypothetical.

output — real, verified
elapsed: 10.01 s
napalm.base.exceptions.ConnectionException -> ConnectionException('Cannot connect to 10.10.10.1')

Real, verified output. NAPALM normalizes failure too -- the underlying Netmiko timeout is caught and re-raised as NAPALM's own ConnectionException, not Netmiko's raw exception text.

Quick checkPredict output
Given the real, verified output above, what exception type actually surfaces when driver.open() fails against an unreachable IOS device?

Closing connections, and a context-manager form

context-manager form — real, verified via NAPALM's mock driver
with driver_cls(hostname="SW1", username="x", password="y", optional_args={"path": "fixtures/sw1"}) as d:
  print("inside with-block, is_alive:", d.is_alive())
print("after with-block (auto-closed)")

__enter__ calls open(); __exit__ calls close() automatically -- verified directly, not assumed.

output — real, verified
inside with-block, is_alive: {'is_alive': True}
after with-block (auto-closed)

Real, verified output. with driver: guarantees close() runs even if an exception is raised inside the block -- the same cleanup guarantee Phase 3.3's Connection class taught by hand with __enter__/__exit__.

Key takeaways

  • get_network_driver(name) returns a class, not a connection -- instantiate it with hostname/username/password, then call open() to actually connect.
  • Every driver shares the same constructor shape across vendors: hostname, username, password, timeout, optional_args.
  • A genuine, source-verified discovery: NAPALM's IOS driver wraps Netmiko internally (device_type='cisco_ios') -- it doesn't reimplement SSH.
  • A real connection failure against an unreachable address (10.01s) surfaces as NAPALM's own normalized ConnectionException, not Netmiko's raw exception.
  • with driver: ... works as a real context manager, calling open()/close() automatically -- verified directly.