Table of Contents
- Overview
- Nornir Result Object: Role and Structure
- Example: Capturing and Using Results
- Key Points for Engineers
- Display and Formatting
- Summary Table: How Nornir Hands Back Results
- Conclusion
Nornir Automation: Result
Overview
The Nornir Result object is a central concept in the Nornir automation framework. It serves as the structured feedback mechanism every time a task runs on a device within your network automation workflows. The Result object collects and organizes the execution outcome—success, failure, details, and outputs—across all devices and tasks, providing deep visibility and control for network engineers.
Why You Need to Know About It
- Error Detection & Troubleshooting: Result objects make it easy to identify which tasks or devices failed, pinpoint exceptions, and retrieve context for rapid troubleshooting.
- Automation Logic: The detailed information carried by each result allows you to write smarter automation, such as automatically retrying failed devices, branching logic, or triggering alerts based on specific outcomes.
- Auditability & Reporting: For compliance or operational oversight, Result objects offer a full, per-device and per-task trail. They can be parsed for logs, dashboards, or aggregated reports.
- Fine-Grained Control: Because Nornir produces a separate result object per task and per device, you can make granular decisions. For example, perform a config diff only when changes have occurred, or escalate issues only for critical hosts.
How It Works
- Execution & Capture: When Nornir runs a task, it creates a Result object that records the primary output (
result
), success or failure flags, exceptions, host identity, whether a change occurred, configuration diffs, and more. - Hierarchical Structure: Results are organized hierarchically. At the top, you have an
AggregatedResult
encompassing all devices. Underneath, each device has aMultiResult
collection for all tasks run on it, and each of those contains aResult
object for a specific task. - Nesting & Subresults: For tasks that themselves involve multiple steps (for example, nested configuration commands), subresults are maintained as a list within the parent result, ensuring full traceability of multi-step workflows.
- Programmable Access: Results can be programmatically examined in Python to automate decision making. For instance, you can iterate through all hosts, check for failures, or extract specific fields (outputs, diffs, exceptions) for further analysis or reporting.
- Formatting & Display: Results are readily displayable in human-readable formats (CLI, logs, dashboards) using helper functions or can be exported as JSON/YAML for integration with other tools.
In summary, the Nornir Result object is not just a return value—it’s a rich, structured source of operational intelligence that empowers network automation to be reliable, auditable, and responsive to real-world challenges. Understanding and utilizing Result objects is fundamental to building resilient, scalable, and maintainable automation systems in modern network engineering.
Nornir Result Object: Role and Structure
The Nornir Result object is a fundamental building block of Nornir, encapsulating the outcome of any task executed across devices. Understanding how this object works is essential for troubleshooting, automation logic, and reporting in network automation workflows.
-
Purpose and Role in Workflows:
The Result object acts as a structured record for every action Nornir performs on a device. It contains detailed status, output, error messages, and metadata for each executed task, ensuring visibility into what was attempted and what happened. -
Key Attributes:
- result: The main output or response from the task (such as CLI command output, API response, parsed data, etc.).
-
failed:
A boolean flag indicating if the task failed (
True
) or succeeded (False
). - exception: Contains any Python exception object raised during task execution, useful for debugging.
- host: The name of the host (device) the result is associated with.
-
changed:
Indicates if the task made changes on the target device (
True
) or not. - diff: Shows the difference between the previous and updated configuration (present when applicable).
- severity_level: Sets the impact level (typically for Nornir’s logging system).
-
Nesting and Hierarchy:
For multi-step tasks or aggregated operations, the Result object can contain a list ofsubresults
, each representing an individual action or step within a larger workflow. This allows fine-grained reporting on complex jobs.
Example:
{
"result": "Command completed successfully",
"failed": false,
"exception": null,
"host": "router-01",
"changed": true,
"diff": "+ interface Loopback10\n+ ip address 10.10.10.1/32",
"severity_level": 0
}
By leveraging the Result object’s structure, engineers can automate decision logic, create robust error handling, and generate detailed operational reports in their Nornir-driven automation pipelines.
Example: Capturing and Using Results
Capturing and working with results in Nornir allows engineers to conditionally handle errors, extract command outputs, create logic-based workflows, or write automation reports. Here’s a step-by-step example using a basic Nornir script:
-
Step 1: Define the Task
You first define a function that represents the task being executed. For example, running a command on network devices:from nornir import InitNornir from nornir_netmiko.tasks import netmiko_send_command def get_interfaces(task): return task.run(task=netmiko_send_command, command_string="show ip interface brief")
-
Step 2: Initialize Nornir and Run the Task
Use your configuration file to initialize Nornir and run the task:nr = InitNornir(config_file="config.yaml") results = nr.run(task=get_interfaces)
-
Step 3: Access and Use Results
Once you have the results, you can iterate through them and access specific fields like output, failure states, and diffs:for host, result in results.items(): print(f"Results for {host}:") for r in result: if r.failed: print("Task failed:", r.exception) else: print(r.result)
-
Step 4: Build Your Own Logic
You can use these structures to automate response triggers, implement retries, or generate reports:if any(r.failed for r in result): # Retry logic or alert alert_engine("Issue detected on device", host)
Sample Output Structure:
{
"router-1": [
{
"result": "Interface IP-Address OK? Method Status...",
"failed": false,
"exception": null,
"changed": false,
"host": "router-1"
}
]
}
By capturing and parsing results, you unlock dynamic control within your Nornir automation pipeline — allowing error handling, real-time decision making, and clean output formatting for logs or dashboards.
Key Points for Engineers
When working with Nornir's Result objects in network automation, understanding these essential practices helps maximize efficiency and reliability:
-
Always Inspect Results
Don’t just assume every task succeeded. Examine thefailed
andexception
attributes of each result object to catch any errors early. This prevents partial configuration and silent failures. -
Leverage Parallel Execution
Nornir excels at executing tasks in parallel across many devices. This dramatically improves speed when automating large-scale changes or verifications. -
Exploit Granularity in Results
Each device and each task yields its own result object, so you can see, log, and act on outcomes at a per-device and per-task level. -
Take Advantage of Built-in Logging
Use Nornir’s logging and output formatting functions (likeprint_result()
) for visibility and to maintain audit trails of everything executed. -
Write Logic Based on Outcomes
Use the structure of result objects to create intelligent automation workflows—automatically retry failed operations, alert on anomalies, or conditionally perform further actions. -
Use Plugins Strategically
Expand Nornir's core functionalities with plugins designed for specific vendor devices or workflows to further customize result handling and task execution. -
Validate and Diff Changes
For configuration tasks, inspect thediff
field (where present) to verify changes and support change-control or compliance reporting requirements.
By keeping these points in mind, network engineers can create robust, scalable, and reliable Nornir-driven automation pipelines that are resilient to errors and easy to maintain.
Display and Formatting
Presenting Nornir results in a clean and readable format is crucial when debugging, auditing, or simply sharing results with other engineers. Nornir provides built-in methods and practices to help display results effectively in scripts, CLI outputs, or external logs. Here’s how:
-
Use the
print_result()
Helper
Theprint_result()
function from Nornir’s utilities module is the quickest way to print results in a tree-like structure.
This displays a nested, readable breakdown of each task, host, and result — including failure flags and output.from nornir_utils.plugins.functions import print_result print_result(result)
-
Customize Output with
rich
For more advanced formatting, you can integrate therich
library to colorize or style the output for CLI tools or TUI dashboards.from rich import print print(f"[green]{result['router1'][0].result}[/green]")
-
Exporting to JSON
When results need to be stored, integrated with external systems, or transmitted via APIs, convert them into JSON format:
This is useful for logging systems, dashboards, or storing daily automation snapshots.import json json_string = json.dumps(result["router1"][0].result, indent=2)
-
Handling Large Outputs
If your commands return extensive data (like entire configuration files or routes), consider trimming, paginating, or filtering the result output for clarity:full_output = result["core-switch"][0].result first_10_lines = "\n".join(full_output.splitlines()[:10])
-
Tabular Formats and Jinja Templates
Format structured data (like interfaces, routes, BGP peers) into fixed-width tables using Jinja2 templates or tabulate:from tabulate import tabulate parsed_output = [ ["Gig0/0", "up", "10.0.0.1"], ["Gig0/1", "down", "-"] ] print(tabulate(parsed_output, headers=["Interface", "Status", "IP"]))
Good formatting practices make results more actionable, easier to monitor, and ready for presentation in automation reports or CI/CD pipelines.
Summary Table: How Nornir Hands Back Results
Nornir structures its results in a hierarchical way that makes it easy to retrieve exactly what you need, whether it’s a global summary, per-device breakdown, or individual task result. Here’s a summary table of the key result objects and what each one organizes:
Object Type | Description | What It Holds | Access Example |
---|---|---|---|
AggregatedResult | Top-level, dict-like object grouping results per host/device | Each key is a hostname; values are MultiResult objects |
result['router1'] |
MultiResult | List-like container for all results of tasks (and subtasks) run on a host | Each item is a Result object for one specific task/subtask |
result['router1'][0] |
Result | Individual object representing outcome of a single task/subtask | Output, failed flag, exception, changed, diff, severity, etc. | result['router1'][0].result result['router1'][0].failed |
Here’s a quick visual to show the hierarchy:
AggregatedResult
├── 'router1': MultiResult
│ ├── Result (task 1)
│ ├── Result (task 2)
├── 'router2': MultiResult
│ ├── Result (task 1)
│ ├── Result (task 2)
This structure lets you easily drill down from the big picture (all devices and tasks) to granular details for precise reporting, debugging, or automation logic.
Conclusion
Throughout this blog post, we explored the core structure, functionality, and power of the Nornir Result object within network automation workflows. Whether you're troubleshooting failed tasks, extracting interface information, or building CI/CD pipeline logic — understanding how Nornir hands back results is key to working smarter, not harder.
Let’s quickly recap the key takeaways:
- 🎯 Result objects are your feedback loop in every automation workflow. They contain output, success/failure status, exceptions, diffs, and more.
- 🔍 Each host and task set receives its own structured result, empowering fine-grained control over monitoring and logic.
- 📊 Formatting tools like
print_result()
,json.dumps()
, ortabulate()
help you display results clearly and readably — great for logs or reports. - ✅ Engineers can use Nornir results to trigger conditionals, retries, notifications, and even decision-making within task chains.
- 📚 Result hierarchies — AggregatedResult > MultiResult > Result — keep your task data well organized, giving you full visibility at every level.
By mastering how results are captured, formatted, and interpreted, you position yourself to build clean, scalable, and intelligent Nornir automations that go beyond simple task execution.
Thanks for following along — and happy automating!
🚀💻🔧