{"id":9006,"library":"genie-libs-health","title":"pyATS Genie Health Checks","description":"genie-libs-health is a Python library within the pyATS framework, providing a robust mechanism for monitoring network device health status. It allows users to define custom health checks using YAML files, which are then executed against devices configured in a pyATS testbed. This library is part of the `genie` ecosystem and is primarily used for automated network device validation and troubleshooting. It is currently at version `26.3` and follows the `genie` release cadence, which typically aligns with `pyATS` monthly releases.","status":"active","version":"26.3","language":"en","source_language":"en","source_url":"https://github.com/CiscoDevNet/genie","tags":["network automation","pyats","genie","health check","cisco","network device"],"install":[{"cmd":"pip install genie-libs-health","lang":"bash","label":"Install genie-libs-health"}],"dependencies":[{"reason":"Core test automation framework required to run testbeds and interact with devices.","package":"pyats"},{"reason":"Core Genie library; genie-libs-health is a sub-library leveraging Genie's operational parsers and device abstractions.","package":"genie"}],"imports":[{"note":"The `Health` class is located within the `genie.libs.health.health` module, not directly under the `genie_libs_health` top-level package name.","wrong":"from genie_libs_health import Health","symbol":"Health","correct":"from genie.libs.health.health import Health"}],"quickstart":{"code":"import yaml\nfrom unittest.mock import Mock # For a truly runnable example without a real device\nfrom genie.libs.health.health import Health\n\n# --- 1. Create a mock device and testbed for demonstration ---\n# In a real scenario, you would load a testbed from a file:\n# from pyats.topology import loader\n# testbed = loader.load('path/to/testbed.yaml')\n# my_device = testbed.devices['your_device_name']\n\n# Mock a device and its connection/execution methods\nmock_device = Mock()\nmock_device.name = \"my_mock_device\"\nmock_device.os = \"iosxe\"\nmock_device.connected = False\nmock_device.api.execute.return_value = {\n    \"show version\": \"Cisco IOS XE Software, Version 17.3.4\",\n    \"show processes cpu sorted\": \"CPU utilization for five seconds: 5%/1%; one minute: 4%; five minutes: 3%\"\n}\n\n# Define connect/disconnect behavior for the mock\ndef mock_connect():\n    print(f\"Attempting to connect to {mock_device.name} (mocked)...\")\n    mock_device.connected = True\n    print(f\"Successfully connected to {mock_device.name} (mocked).\")\nmock_device.connect.side_effect = mock_connect\n\ndef mock_disconnect():\n    print(f\"Disconnecting from {mock_device.name} (mocked)...\")\n    mock_device.connected = False\nmock_device.disconnect.side_effect = mock_disconnect\n\n# Create a mock testbed containing our mock device\nmock_testbed = Mock()\nmock_testbed.devices = {'my_mock_device': mock_device}\nmock_testbed.name = \"mock_testbed\"\n\n# --- 2. Define a simple health check YAML in-memory ---\nhealth_yaml_content = \"\"\"\nhealth_check_sections:\n  section_version_check:\n    commands:\n      show version:\n        - '.*Cisco IOS XE Software.*' # Checks for IOS XE in 'show version' output\n  section_cpu_usage_check:\n    commands:\n      show processes cpu sorted:\n        - 'CPU utilization for five seconds: [0-9]{1,2}%/' # Checks if CPU is valid percentage\n\"\"\"\nhealth_data = yaml.safe_load(health_yaml_content)\n\n# --- 3. Initialize and run Health checks ---\ntry:\n    # Use the mock device (in a real scenario, this would be from testbed.devices)\n    my_device = mock_testbed.devices['my_mock_device']\n    my_device.connect() # This will call our mock_connect function\n\n    # Create Health object with the device and parsed health data\n    health = Health(device=my_device, health_data=health_data)\n\n    # Run all defined health checks\n    print(f\"\\nRunning health checks on {my_device.name}...\")\n    health_result = health.check_all()\n\n    # Print results\n    print(\"\\nHealth Check Results Summary:\")\n    for section, result in health_result.items():\n        print(f\"  Section: '{section}' -> Status: {result['status']}\")\n        if result['status'] == 'Fail':\n            print(f\"    Reason: {result.get('reason', 'No specific reason provided.')}\")\n            for command, cmd_result in result.get('commands', {}).items():\n                if cmd_result.get('status') == 'Fail':\n                    print(f\"      Command '{command}' failed: {cmd_result.get('reason', 'N/A')}\")\n\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")\nfinally:\n    if my_device and my_device.connected:\n        my_device.disconnect()","lang":"python","description":"This quickstart demonstrates how to define health checks using a YAML structure, initialize the `Health` object with a device (mocked for this example), and execute the checks. In a real scenario, `my_device` would be an actual connected device loaded from a pyATS testbed file. The example uses `unittest.mock` to make the code runnable without requiring actual device connectivity."},"warnings":[{"fix":"Always install `pyats` and `genie-libs-health` (which pulls `genie`) from the same major release cycle. E.g., if `pyats` is 24.4, ensure `genie` is also from a compatible 24.x release. Check official pyATS documentation for version compatibility matrices.","message":"pyATS and Genie (including genie-libs-health) versions are tightly coupled. Installing incompatible versions can lead to `ImportError`, `AttributeError`, or unexpected behavior.","severity":"breaking","affected_versions":"All versions, especially when upgrading."},{"fix":"Before running health checks, ensure your `testbed.yaml` is accurate and that you can manually connect to the devices using the specified credentials and protocols. Use `pyats run job --testbed testbed.yaml` with a simple connection script to verify connectivity.","message":"Health checks require a properly configured pyATS testbed and reachable network devices. Common failures stem from incorrect device IPs, usernames, passwords, or network connectivity issues.","severity":"gotcha","affected_versions":"All versions."},{"fix":"Carefully review your `health_check.yaml` file for correct YAML syntax (indentation, colons, list items) and ensure commands and patterns match device output expectations. Refer to the `genie-libs-health` documentation for the correct YAML schema.","message":"Health check definitions in YAML must strictly adhere to the `genie-libs-health` schema. Syntax errors, incorrect command names, or malformed regex patterns will lead to runtime exceptions or incorrect check results.","severity":"gotcha","affected_versions":"All versions."},{"fix":"If a health check fails unexpectedly, debug the underlying command execution and parsing. You can manually run `device.execute('show command')` and `device.parse('show command')` to isolate parsing issues before involving health checks.","message":"Underlying Genie operational parsers (`genie.libs.ops`) must successfully parse command output for health checks to function. If a parser fails, the health check for that command will report an error.","severity":"gotcha","affected_versions":"All versions."}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"The `Health` class is nested within the `genie.libs.health.health` module. Use `from genie.libs.health.health import Health`.","cause":"Attempting to import the `Health` class directly from the top-level package name `genie_libs_health`.","error":"ImportError: cannot import name 'Health' from 'genie_libs_health'"},{"fix":"Verify the path to your `testbed.yaml` file. Check its YAML syntax. Ensure the device IP, username, password, and connection protocol are correct and that the device is network-reachable from where the script is run.","cause":"The pyATS testbed file is missing, malformed, or the specified device in the testbed cannot be reached or authenticated.","error":"pyats.topology.loader.exceptions.InvalidTestbedError: Cannot load testbed 'None' or Failed to connect to device 'my_device'"},{"fix":"Ensure `testbed.devices['my_device']` successfully retrieves a device object and that `my_device.connect()` completes without exceptions before attempting to run health checks.","cause":"This usually indicates that the device object from the testbed was not properly loaded, or `device.connect()` failed to establish a connection, leaving the device object in an unusable state.","error":"AttributeError: 'NoneType' object has no attribute 'cli' (or similar during device interaction)"},{"fix":"Review the health check YAML file carefully for any syntax errors. Use a YAML linter or validator to identify issues. Pay close attention to indentation and proper key-value pairing.","cause":"The health check YAML file (`health_check.yaml`) contains syntax errors, such as incorrect indentation, missing colons, or improper structure.","error":"yaml.scanner.ScannerError: while scanning a simple key"}]}