NetAuto Academy

Netmiko Fundamentals

Connecting to a Device with Netmiko

Beginner13 min read

What you'll learn

  • How to open a connection with ConnectHandler and close it with disconnect()
  • Two safe ways to supply credentials at runtime: getpass() and environment variables
  • The two exceptions a connection attempt can raise, and what each one means
  • Why a connection should always be closed, not just left open
  • How this maps onto the connection/check function this module is building toward
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

Opening a connection

ConnectHandler is the function that actually opens the SSH session. It takes the connection parameters from the last lesson and returns a connection object you can run commands on:

connect_example.py
from netmiko import ConnectHandler

device = {
  "device_type": "cisco_ios",
  "host": "192.168.1.1",   # placeholder — use your own lab device's IP
  "username": "labuser",   # placeholder — never a real credential
  "password": "labpass",   # placeholder — see the next section for the real way to do this
}

connection = ConnectHandler(**device)
print("Connected.")

connection.disconnect()
print("Disconnected.")

**Never run this with real credentials written in the file.** This example exists to show the shape of the call — the next section replaces the hardcoded username/password with a safe runtime prompt.

**device unpacks the dictionary into the keyword arguments ConnectHandler expects — the same dictionary-unpacking shape, just applied to a function call instead of a data structure.

The connection lifecycle

  1. Build connection parametersdevice_type, host, username, password
  2. ConnectHandler(**device)opens the SSH session
  3. Authenticatedevice checks the credentials
  4. Session openready to send commands
  5. disconnect()closes the session cleanly

Always close what you open

A connection left open holds a resource on the device — Cisco switches have a limited number of concurrent SSH sessions (VTY lines). A script that connects to fifty devices and never disconnects can genuinely lock other engineers out of a device. Calling disconnect() when you're done isn't optional cleanup — it's part of doing this correctly.

Quick checkConcept check
Why does a script need to call connection.disconnect() when it's finished, rather than just letting the script end?

Supplying credentials safely

Never write a real username or password directly into a script. Two safe, standard ways to supply them at runtime instead:

credentials_getpass.py
import getpass
from netmiko import ConnectHandler

username = input("Username: ")
password = getpass.getpass("Password: ")

device = {
  "device_type": "cisco_ios",
  "host": "192.168.1.1",   # placeholder
  "username": username,
  "password": password,
}

connection = ConnectHandler(**device)

input() prompts for the username in plain text; getpass.getpass() prompts for the password without echoing it to the screen — the same behavior as a terminal login prompt. Nothing is ever written to a file.

credentials_env.py
import os
from netmiko import ConnectHandler

device = {
  "device_type": "cisco_ios",
  "host": "192.168.1.1",   # placeholder
  "username": os.environ["NETMIKO_USERNAME"],
  "password": os.environ["NETMIKO_PASSWORD"],
}

connection = ConnectHandler(**device)

os.environ reads values set outside the script — in the terminal session or a scheduler's configuration, never written into the code itself. This is the better fit for a script that runs unattended, on a schedule, without anyone at the keyboard to type a password.

Quick checkIdentify the correct code
Which line correctly reads a password without echoing it to the screen?
Quick checkMyth check
Is it acceptable to put a real device's username and password directly into a devices.csv inventory file, as long as the file stays on the engineer's own laptop?
Quick checkScenario
A script needs to run unattended every night on a schedule, with no one available to type a password. Which credential method fits better — getpass() or environment variables?

What can go wrong when connecting

safe_connect.py
from netmiko import ConnectHandler, NetmikoTimeoutException, NetmikoAuthenticationException

try:
  connection = ConnectHandler(**device)
except NetmikoTimeoutException:
  print(f"{device['host']}: did not respond — check the IP and network path")
except NetmikoAuthenticationException:
  print(f"{device['host']}: rejected the credentials")

Two distinct exceptions for two distinct problems. A timeout means the device never answered at all — wrong IP, no route, or it's down. An authentication failure means it answered, but didn't accept the username or password.

What a real timeout actually looks like

Testing this against a guaranteed-unreachable address confirms Netmiko's real behavior: a connection attempt to an address with nothing listening raises NetmikoTimeoutException with a message that starts "TCP connection to device failed" and lists likely causes — wrong hostname/IP, wrong port, or a firewall in the way. That's exactly the category of problem a timeout signals: the network path itself, not the credentials.

Quick checkConcept check
A connection attempt raises NetmikoAuthenticationException. What does this tell you, compared to NetmikoTimeoutException?

Key takeaways

  • ConnectHandler(**device) opens the SSH session; connection.disconnect() closes it — always close what you open.
  • getpass() and input() prompt for credentials interactively; environment variables supply them for unattended, scheduled scripts — neither ever writes a credential into a file.
  • NetmikoTimeoutException means the device never responded (a network-path problem); NetmikoAuthenticationException means it responded but rejected the credentials — different problems, different responses.
  • This lesson's try/except around ConnectHandler is the beginning of the real connection/check function this module is building — the same shape as Phase 2.6's try/except around simulate_connection().