Inventory-driven Cisco IOS automation with Python, Netmiko, YAML, Jinja2, and pytest.
A modular network automation toolkit built and validated against a live six-device Cisco IOS environment in EVE-NG.
The project provides inventory management, runtime credential loading, SSH connection handling, running-configuration backups, Jinja2 rendering, deployment components, post-change validation, rollback logic, structured logging, and operational reporting.
| Validation | Result |
|---|---|
| Live Netmiko SSH connectivity | 6/6 devices |
| Automated running-config backups | 6/6 devices |
| Automated pytest suite | 30/30 passed |
| Remote management protocol | SSHv2 |
| Credential handling | Runtime environment variables |
| Lab platform | EVE-NG Community |
The architecture separates device data, credentials, connection management, configuration generation, change execution, validation, rollback, and reporting into dedicated components.
The controlled change path is:
Load inventory and runtime credentials
-> Establish SSH connection
-> Create pre-change backup
-> Render configuration
-> Deploy configuration
-> Run post-change validation
-> Evaluate result
-> PASS: Generate operational report
-> FAIL: Execute rollback
-> Validate restored state
-> Generate operational report
Live execution currently covers SSH connectivity and running-configuration backup. Deployment, validation, rollback, and reporting are implemented as reusable components and covered by automated tests.
The lab contains redundant Core, Distribution, and Access layers. Each device also connects to a dedicated management network used for Netmiko SSH automation.
| Device | Network Role | Management IP |
|---|---|---|
CORE-01 |
Core | 192.168.116.11 |
CORE-02 |
Core | 192.168.116.12 |
DIST-01 |
Distribution | 192.168.116.21 |
DIST-02 |
Distribution | 192.168.116.22 |
ACCESS-01 |
Access | 192.168.116.31 |
ACCESS-02 |
Access | 192.168.116.32 |
- YAML-based multi-device inventory
- Runtime credential loading through environment variables
- Reusable Netmiko SSH connection manager
- Multi-device command execution
- Read-only connectivity validation
- Timestamped running-configuration backups
- Jinja2 configuration rendering
- Controlled deployment components
- Post-change validation logic
- Rollback and post-rollback validation
- Structured logging and exception handling
- HTML operational report generation
- Automated testing with pytest
Problem: Device passwords and enable secrets must not be stored in source code or committed inventory files.
Solution: Credentials are loaded into environment variables at runtime. The committed inventory contains only sanitized example data, and operational files are excluded through .gitignore.
Problem: Manually connecting to every device and running the same command is slow and inconsistent.
Solution: Device information is loaded from a shared YAML inventory and processed through reusable connection and execution components.
Problem: A failed configuration change can leave a device in an unknown or partially modified state.
Solution: The workflow creates a pre-change running-configuration backup and includes rollback and post-rollback validation components.
Problem: A command completing without an exception does not confirm that the intended network state was achieved.
Solution: Validation logic evaluates post-change command output and determines whether the workflow should pass, fail, or trigger rollback.
Problem: Running configurations, logs, reports, credentials, and local inventory files may contain sensitive information.
Solution: Operational artifacts are stored locally and excluded from Git. Only sanitized configuration examples and validation screenshots are committed.
Problem: On Windows, pytest may fail during cleanup when the default temporary directory remains locked.
Solution: Tests can use a project-local temporary directory through --basetemp. The local pytest directory is excluded from Git.
| Capability | Automated Coverage | Live or Local Evidence |
|---|---|---|
| YAML inventory loading | Yes | Used by live scripts |
| Runtime credential loading | Yes | Used in live lab |
| Netmiko SSH connectivity | Yes | 6/6 devices |
| Running-config backup | Yes | 6/6 devices |
| Jinja2 configuration rendering | Yes | Locally validated |
| Configuration deployment | Yes | Component-tested |
| Post-change validation | Yes | Component-tested |
| Rollback workflow | Yes | Component-tested |
| HTML operational reporting | Yes | Locally generated |
| Error and exception handling | Yes | Automated tests |
The connectivity workflow opens an SSH session to every inventory device, validates the prompt, and confirms the configured hostname.
The backup workflow retrieves the running configuration from each device and writes it to a timestamped, device-specific directory.
The NetAuto CLI loads the sanitized YAML inventory and displays all six managed Cisco IOS devices with their management addresses, network roles, and device types.
The templating workflow converts structured VLAN definitions into consistent Cisco IOS configuration commands before controlled deployment.
The test suite covers inventory parsing, credential handling, connection behavior, configuration backup, template rendering, deployment components, validation, rollback, reporting, and exception handling.
| Path | Purpose |
|---|---|
inventory/ |
Sanitized inventory example and ignored operational inventory |
netauto/ |
Core Python automation modules |
scripts/ |
Live connectivity and backup validation scripts |
templates/ |
Jinja2 configuration templates |
tests/ |
Automated pytest suite |
docs/architecture/ |
Architecture and EVE-NG topology diagrams |
docs/evidence/ |
Screenshots of validated results |
| Module | Responsibility |
|---|---|
inventory.py |
Load and validate YAML device inventory |
credentials.py |
Read runtime environment credentials |
connection.py |
Build and manage Netmiko sessions |
executor.py |
Execute commands across managed devices |
backup.py |
Create timestamped running-config backups |
templating.py |
Render Jinja2 configuration templates |
deployment.py |
Apply controlled configuration changes |
validation.py |
Evaluate post-change state |
rollback.py |
Restore configuration after failed validation |
reporting.py |
Generate operational reports |
logging_config.py |
Configure structured logging |
exceptions.py |
Define project-specific exceptions |
- Python 3.12
- Cisco IOS devices reachable through SSHv2
- EVE-NG or another supported network lab platform
- A dedicated or logically separated management network
- Valid credentials for the managed devices
git clone https://github.com/MansourMutlaq/Cisco-Network-Automation.git
cd Cisco-Network-Automation
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txtCreate the local operational inventory from the sanitized example:
Copy-Item .\inventory\devices.example.yml .\inventory\devices.ymlUpdate inventory/devices.yml with the target device names, management addresses, ports, and device types.
Display the loaded inventory:
python -m netauto.cli `
--inventory .\inventory\devices.yml `
inventoryThe operational inventory/devices.yml file is excluded from Git.
Load credentials into the current PowerShell process:
$cred = Get-Credential `
-UserName netadmin `
-Message "Cisco IOS credentials"
$env:NETAUTO_USERNAME = $cred.UserName
$env:NETAUTO_PASSWORD = $cred.GetNetworkCredential().Password
$env:NETAUTO_SECRET = $env:NETAUTO_PASSWORDSet NETAUTO_SECRET separately when the enable secret differs from the login password.
Credentials are not written to the repository. Environment variables remain available only inside the current PowerShell process.
python -m netauto.cli `
--inventory .\inventory\devices.yml `
inventorypython -m scripts.live_connectivity_testExpected result:
Successful: 6/6
NETMIKO CONNECTIVITY TEST PASSED
python -m scripts.live_backupExpected result:
Successful backups: 6/6
CONFIGURATION BACKUP TEST PASSED
Backups are stored beneath:
backups/<device-name>/
python -m pytest -qExpected result:
30 passed
Use a project-local temporary directory when Windows prevents pytest from cleaning its default temporary directory:
$runTemp = Join-Path $PWD ".pytest-temp\run"
New-Item -ItemType Directory `
-Path $runTemp `
-Force | Out-Null
python -m pytest -q --basetemp="$runTemp"Confirm that the environment variables are loaded in the same PowerShell session used to run the scripts:
Test-Path Env:NETAUTO_USERNAME
Test-Path Env:NETAUTO_PASSWORD
Test-Path Env:NETAUTO_SECRETAll three commands should return True.
Check that:
- The EVE-NG node is running.
- The management interface is operational.
- The device management IP matches the inventory.
- RSA keys exist on the Cisco IOS device.
- SSH version 2 is enabled.
- The VTY lines use
login localand allow SSH.
Useful Cisco IOS commands:
show ip interface brief
show ip ssh
show running-config | section line vty
show running-config | include username
Create the operational inventory from the committed example:
Copy-Item .\inventory\devices.example.yml .\inventory\devices.ymlRun the test suite with the project-local --basetemp directory shown above.
The repository excludes the following local and operational data:
- Runtime inventory files
- Running-configuration backups
- Environment files
- Credentials and enable secrets
- Generated logs and reports
- Python cache files
- Pytest cache and temporary directories
- Virtual environments
The committed inventory example is sanitized and contains no device passwords or enable secrets.
- Live lab validation currently covers SSH connectivity and running-configuration backup.
- Deployment and rollback components have automated coverage but have not yet been exercised across the complete six-device topology.
- Execution is currently sequential.
- The lab is based on Cisco IOS virtual devices in EVE-NG.
- Physical hardware and multi-vendor platforms have not yet been validated.
- Execute controlled configuration deployment and rollback drills in an isolated lab VLAN
- Add GitHub Actions continuous integration for the automated test suite
- Add bounded parallel execution for larger device inventories
- Add configuration diff and approval before deployment
- Add Cisco IOS-XE RESTCONF support
- Add Nornir-based orchestration
- Add multi-vendor inventory and driver support
- Add GitOps-based configuration review and change approval
- Expand HTML reporting with per-device change and validation details
This project is licensed under the MIT License.





