Skip to content

Cisco IOS/IOS-XE Health Check Guide

netops-toolkit provides a comprehensive health-check module for Cisco IOS 15.x+ and IOS-XE 16.x+ devices. All checks are read-only — no configuration is modified.

Supported Device Types

vendor value Netmiko driver Typical hardware
cisco_ios cisco_ios ISR, Catalyst (IOS 15.x+)
cisco_xe cisco_xe ASR, CSR, Catalyst 9000 (IOS-XE 16.x+)
cisco_xr cisco_xr ASR 9000, NCS (IOS-XR) — BGP only

Checks Performed

Check Command Alert condition
CPU show processes cpu 1-min average ≥ threshold (default 80%)
Memory show processes memory Used % ≥ threshold (default 85%)
Interface errors show interfaces Any interface has non-zero CRC/input/output errors or drops
Syslog show logging Severity 0–3 events present
BGP show ip bgp summary Any peer not in Established state
OSPF show ip ospf neighbor Any adjacency not in FULL state
Environment show environment all Any fan/temperature/PSU not OK
Uptime/reload show version Informational only (never alerts)

Inventory Configuration

defaults:
  username: admin
  transport: ssh

devices:
  core-sw-01:
    host: 10.0.1.1
    vendor: cisco_ios
    groups: [core, cisco]

  dist-sw-01:
    host: 10.0.1.2
    vendor: cisco_xe
    groups: [distribution, cisco]

Running from the CLI

# Single device — all checks
python -m netops.check.cisco --host 10.0.1.1 --user admin \
    --threshold cpu=80,mem=85 --json

# All devices in group
python -m netops.check.cisco \
    --inventory examples/inventory.yaml \
    --group cisco \
    --threshold cpu=80,mem=85

# Skip BGP and OSPF (e.g. pure L2 switch)
python -m netops.check.cisco --host 10.0.1.1 --user admin \
    --no-bgp --no-ospf

# Exit with code 1 when any alert fires (for CI/CD gates)
python -m netops.check.cisco \
    --inventory examples/inventory.yaml \
    --fail-on-alert

Example output:

✅ 10.0.1.1 [2026-03-24T12:00:00Z]
   CPU : 8.0% (threshold 80.0%)
   MEM : 35.0% (threshold 85.0%)
   IFACE ERRORS: 0/24 interfaces with errors
   LOGS: 0 critical, 0 major
   BGP: 4/4 established (0 down)
   OSPF: 3/3 FULL (0 not FULL)
   ENV: OK  fans=2  temps=2  psu=2
   UPTIME: 10 weeks, 2 days, 14 hours, 56 minutes  IOS 16.12.4
   RELOAD: Reload command

Python API

Running all checks

from netops.check.cisco import run_cisco_health_check, build_cisco_health_report
from netops.core.connection import ConnectionParams

params = ConnectionParams(
    host="10.0.1.1",
    username="admin",
    password="s3cr3t",
    device_type="cisco_ios",
)

result = run_cisco_health_check(
    params,
    cpu_threshold=80.0,
    mem_threshold=85.0,
    include_bgp=True,
    include_ospf=True,
    include_environment=True,
)

print(result["overall_alert"])   # True / False
print(result["checks"]["cpu"]["utilization"])
print(result["checks"]["bgp"]["not_established"])
print(result["checks"]["ospf"]["not_full"])
print(result["checks"]["uptime"]["uptime"])

Aggregated report across multiple routers

results = [run_cisco_health_check(p) for p in device_params]
report  = build_cisco_health_report(results)

print(report["devices"])               # total devices polled
print(report["bgp_alerts"])            # devices with BGP peer(s) down
print(report["ospf_alerts"])           # devices with OSPF adjacency issues
print(report["environment_alerts"])    # devices with hardware issues

Individual check functions

from netops.check.cisco import (
    check_cisco_cpu,
    check_cisco_memory,
    check_cisco_interfaces,
    check_cisco_logs,
    check_cisco_bgp,
    check_cisco_ospf,
    check_cisco_environment,
    check_cisco_uptime,
)

with DeviceConnection(params) as conn:
    cpu  = check_cisco_cpu(conn, threshold=80.0)
    mem  = check_cisco_memory(conn, threshold=85.0)
    ifc  = check_cisco_interfaces(conn)
    logs = check_cisco_logs(conn)
    bgp  = check_cisco_bgp(conn)
    ospf = check_cisco_ospf(conn)
    env  = check_cisco_environment(conn)
    ver  = check_cisco_uptime(conn)

Parsers

OSPF neighbors

from netops.parsers.cisco import parse_ospf_neighbors

output = """
Neighbor ID     Pri   State           Dead Time   Address         Interface
192.168.1.2       1   FULL/DR         00:00:37    10.0.0.2        GigabitEthernet0/0
192.168.1.3       1   FULL/BDR        00:00:38    10.0.0.3        GigabitEthernet0/0
192.168.1.4       0   INIT/DROTHER    00:00:35    10.0.0.4        GigabitEthernet0/1
"""

neighbors = parse_ospf_neighbors(output)
# [
#   {"neighbor_id": "192.168.1.2", "priority": 1, "state": "FULL/DR",
#    "dead_time": "00:00:37", "address": "10.0.0.2",
#    "interface": "GigabitEthernet0/0", "is_full": True},
#   {"neighbor_id": "192.168.1.3", "priority": 1, "state": "FULL/BDR",
#    "dead_time": "00:00:38", "address": "10.0.0.3",
#    "interface": "GigabitEthernet0/0", "is_full": True},
#   {"neighbor_id": "192.168.1.4", "priority": 0, "state": "INIT/DROTHER",
#    "dead_time": "00:00:35", "address": "10.0.0.4",
#    "interface": "GigabitEthernet0/1", "is_full": False},
# ]

Environment

from netops.parsers.cisco import parse_environment_cisco

output = """
Switch 1 FAN 1 is OK
Switch 1 FAN 2 is OK
Switch 1: TEMPERATURE is OK
SYSTEM INLET       : 28 Celsius, Critical threshold is 60 Celsius
SYSTEM OUTLET      : 35 Celsius, Critical threshold is 65 Celsius
Switch 1: POWER-SUPPLY 1 is PRESENT
Switch 1: POWER-SUPPLY 2 is NOT PRESENT
"""

env = parse_environment_cisco(output)
# {
#   "fans":           [{"name": "FAN1", "status": "OK", "ok": True}, ...],
#   "temperatures":   [{"name": "TEMPERATURE", "celsius": None, "status": "OK", "ok": True},
#                      {"name": "SYSTEM INLET", "celsius": 28, "status": "OK", "ok": True}, ...],
#   "power_supplies": [{"name": "PS1", "status": "PRESENT", "ok": True},
#                      {"name": "PS2", "status": "NOT PRESENT", "ok": False}],
#   "overall_ok":     False,   # PS2 not present
# }

Version / uptime

from netops.parsers.cisco import parse_version_cisco

output = """
Cisco IOS XE Software, Version 16.12.4
cisco C9300-48P (X86) processor with 1393712K bytes of memory.
Router uptime is 10 weeks, 2 days, 14 hours, 56 minutes
Last reload reason: Reload command
System image file is "bootflash:cat9k_iosxe.16.12.04.SPA.bin"
"""

info = parse_version_cisco(output)
# {
#   "version":       "16.12.4",
#   "platform":      "C9300-48P",
#   "uptime":        "10 weeks, 2 days, 14 hours, 56 minutes",
#   "reload_reason": "Reload command",
#   "image":         "bootflash:cat9k_iosxe.16.12.04.SPA.bin",
# }

Command Templates

from netops.templates.cisco_ios import SHOW, HEALTH

# Standard show commands
print(SHOW["version"])          # show version
print(SHOW["ospf_neighbors"])   # show ip ospf neighbor
print(SHOW["environment"])      # show environment all

# Health check commands
print(HEALTH["cpu"])            # show processes cpu sorted | head 20
print(HEALTH["memory"])         # show processes memory sorted | head 20
print(HEALTH["bgp_summary"])    # show ip bgp summary
print(HEALTH["ospf_neighbors"]) # show ip ospf neighbor
print(HEALTH["environment"])    # show environment all
print(HEALTH["version"])        # show version

Result Schema

Every check function returns a dict that always includes an alert key. The composite run_cisco_health_check wraps all checks under a checks dict and sets overall_alert when any individual check fires:

{
  "host": "10.0.1.1",
  "timestamp": "2026-03-24T12:00:00Z",
  "success": true,
  "checks": {
    "cpu":              {"utilization": 8.0,  "threshold": 80.0, "alert": false, "raw": {...}},
    "memory":           {"utilization": 35.0, "threshold": 85.0, "alert": false, "raw": {...}},
    "interface_errors": {"total": 24, "with_errors": 0, "alert": false, "interfaces": [...]},
    "logs":             {"critical_count": 0, "major_count": 0,  "alert": false, "events": []},
    "bgp":              {"total": 4, "established": 4, "not_established": 0, "alert": false, "peers": [...]},
    "ospf":             {"total": 3, "full": 3, "not_full": 0, "alert": false, "neighbors": [...]},
    "environment":      {"overall_ok": true,  "alert": false, "fans": [...], "temperatures": [...], "power_supplies": [...]},
    "uptime":           {"uptime": "10 weeks, ...", "version": "16.12.4", "reload_reason": "Reload command", "alert": false}
  },
  "overall_alert": false,
  "error": null
}