{"id":8791,"library":"yang.connector","title":"YANG Connector","description":"YANG Connector is a Python package providing tools for testing YANG models via NETCONF and RESTCONF protocols. Primarily, it offers a NETCONF client by wrapping the `ncclient` library and integrates seamlessly with the pyATS framework. The library is actively maintained, with the current version being 26.3, and supports NETCONF v1.0 and v1.1.","status":"active","version":"26.3","language":"en","source_language":"en","source_url":"https://github.com/CiscoTestAutomation/yang.git","tags":["YANG","NETCONF","RESTCONF","network automation","Cisco","pyATS","network programming"],"install":[{"cmd":"pip install yang.connector","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"yang.connector.Netconf wraps the ncclient library for NETCONF protocol implementation.","package":"ncclient"},{"reason":"yang.connector is integrated into the pyATS framework and its Netconf class is based on pyATS BaseConnection.","package":"pyats"}],"imports":[{"symbol":"Netconf","correct":"from yang.connector import Netconf"},{"note":"For GNMI client functionality, import from the 'gnmi' submodule.","symbol":"Gnmi","correct":"from yang.connector.gnmi import Gnmi"}],"quickstart":{"code":"import os\nfrom pyats.topology import loader\n\n# Define device connection details using environment variables for security\nDEVICE_IP = os.environ.get('YANG_CONNECTOR_DEVICE_IP', 'your_device_ip')\nDEVICE_PORT = int(os.environ.get('YANG_CONNECTOR_DEVICE_PORT', 830)) # Default NETCONF port\nUSERNAME = os.environ.get('YANG_CONNECTOR_USERNAME', 'admin')\nPASSWORD = os.environ.get('YANG_CONNECTOR_PASSWORD', 'admin')\n\n# A minimal pyATS Testbed YAML string for demonstration\ntestbed_yaml = f'''\ndevices:\n  my_device:\n    os: iosxe\n    connections:\n      netconf:\n        class: yang.connector.Netconf\n        ip: {DEVICE_IP}\n        port: {DEVICE_PORT}\n        protocol: netconf\n        credentials:\n          default:\n            username: {USERNAME}\n            password: {PASSWORD}\n'''\n\ntry:\n    # Load the testbed from the YAML string\n    testbed = loader.load(testbed_yaml)\n    device = testbed.devices['my_device']\n\n    # Establish connection\n    device.connect(via='netconf', init_exec_alias=False)\n    print(f\"Successfully connected to {device.name} via NETCONF.\")\n\n    # Example: Get configuration using get_config()\n    # For a full configuration, an empty filter can be used\n    # For specific data, provide an XML filter string\n    filter_xml = '<filter type=\"subtree\"><interfaces/></filter>'\n    config_data = device.netconf.get_config(source='running', filter=filter_xml)\n    print(\"\\nRetrieved configuration (filtered for interfaces):\\n\")\n    print(config_data.data_xml)\n\n    # Example: Get capabilities\n    print(\"\\nServer Capabilities:\")\n    for cap in device.netconf.server_capabilities:\n        print(f\"- {cap}\")\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\nfinally:\n    # Disconnect from the device\n    if 'device' in locals() and device.is_connected('netconf'):\n        device.disconnect(via='netconf')\n        print(f\"Disconnected from {device.name}.\")\n","lang":"python","description":"This quickstart demonstrates how to connect to a network device using `yang.connector.Netconf` via the pyATS testbed loader. It then retrieves a filtered configuration (e.g., interfaces) and lists the device's NETCONF capabilities. Credentials should be provided via environment variables for security."},"warnings":[{"fix":"Use the `edit_config()` method instead for sending configuration changes. The `request()` method can also be used for raw RPC requests.","message":"The `configure()` method in `yang.connector.Netconf` is a placeholder and will raise an exception. It is not supported for NETCONF operations.","severity":"breaking","affected_versions":"All versions"},{"fix":"Ensure that the device's RPC replies conform to expected NETCONF standards and that message-ids are correctly handled if manually constructed. Review `ncclient` documentation for error handling.","message":"When using `request()` or other methods, if the NETCONF `rpc-reply` is in a wrong format, or if `message-id` is missing/mismatched, `ncclient` (which `yang.connector` wraps) may raise an `OperationError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Increase the `timeout` parameter when establishing the connection or when making the `request()` call, especially for large queries or slow devices. The default timeout is 30 seconds.","message":"The `request()` method in `Netconf` can raise a `TimeoutExpiredError` if the device does not send an `rpc-reply` within the specified timeout duration.","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":"Replace calls to `device.netconf.configure(msg)` with `device.netconf.edit_config(target='running', config=msg)` (or `candidate`).","cause":"Attempting to use the `configure()` method, which is not implemented for `yang.connector.Netconf`.","error":"Exception: configure is not a supported method of this Netconf class, since a more suitable method, edit_config, is recommended."},{"fix":"When connecting or calling `request()`, set a larger `timeout` value: `device.connect(timeout=60)` or `device.netconf.request(rpc_message, timeout=120)`.","cause":"The network device took too long to respond to an RPC request, exceeding the configured timeout.","error":"ncclient timed out while waiting for an rpc-reply."},{"fix":"This often indicates a non-compliant NETCONF server or an issue with how the RPC request was formulated if done manually. Verify server compliance or ensure `ncclient` is correctly handling RPC message IDs.","cause":"The NETCONF server's reply did not include a `message-id` attribute or it did not match the sent request's `message-id`.","error":"ncclient.operations.errors.OperationError: Missing <message-id> attribute in rpc-reply."}]}