diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index 9b57b97b8..f229d3688 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -9,6 +9,8 @@ All notable changes to the project are documented in this file. ### Changes - Upgrade Linux kernel to 6.12.50 (LTS) +- Extend NETCONF and RESTCONF scripting documentation with operational + data examples, discovery patterns, and common workflow examples, issue #1156 ### Fixes diff --git a/doc/scripting-netconf.md b/doc/scripting-netconf.md new file mode 100644 index 000000000..e796c702e --- /dev/null +++ b/doc/scripting-netconf.md @@ -0,0 +1,738 @@ +# Scripting with NETCONF + +NETCONF (Network Configuration Protocol) provides a standardized mechanism for +managing network devices using XML-based RPC operations over SSH (port 830). +This guide shows practical examples for interacting with Infix using NETCONF. + +NETCONF offers robust capabilities for network automation: + +- **Transactional operations**: Validate before commit, rollback on error +- **Fine-grained locking**: Prevent concurrent configuration conflicts +- **Structured data**: XML with YANG schema validation +- **Standardized operations**: Get, edit-config, copy-config, etc. + +## NETCONF vs RESTCONF + +Both protocols use the same YANG data models, but differ in approach: + +| Feature | NETCONF | RESTCONF | +|------------|--------------------|---------------------------------| +| Transport | SSH | HTTPS | +| Encoding | XML | JSON/XML | +| Operations | RPC-based | REST/HTTP methods | +| Best for | Automation scripts | Web integration, simple queries | + +Choose NETCONF when you need: + +- Transactional configuration changes +- Configuration validation before commit +- Locking to prevent concurrent changes +- Integration with existing NETCONF tooling + +Choose RESTCONF for: + +- Simple queries and updates +- Web-based applications +- When you prefer JSON over XML +- RESTful API patterns + +## Quick Start with netopeer2-cli + +`netopeer2-cli` is an interactive NETCONF client, useful for learning and +testing. Install it: + +```bash +~$ sudo apt install netopeer2-cli +``` + +Connect to your Infix device: + +```bash +~$ netopeer2-cli +> connect --host example.local --login admin +admin@example.local password: +> status +Current NETCONF session: + ID : 1 + Host : example.local + Port : 830 + Transport : SSH + Capabilities: 35 +``` + +### Basic Operations in netopeer2-cli + +**Get entire configuration:** + +``` +> get-config --source running +``` + +**Get specific subtree (hostname):** + +``` +> get-config --source running --filter-xpath /system/hostname + + + example + + +``` + +**Get operational state:** + +``` +> get --filter-xpath /interfaces +``` + +**Edit configuration:** + +``` +> edit-config --target candidate --config=/tmp/config.xml +> commit +``` + +**Disconnect:** + +``` +> disconnect +> quit +``` + +## Discovery & Common Patterns + +Before working with specific configuration items, you often need to discover +what exists on the system. This section shows common discovery patterns and +practical workflows. + +### Discovering Available Interfaces + +**List all interface names:** + +```xml + + + + + + + + + + + +``` + +Using netopeer2-cli: + +``` +> get --filter-xpath /interfaces/interface/name +``` + +This returns all interface names, useful for iterating through interfaces +in scripts. + +### Get All YANG Capabilities + +Discover which YANG modules and features are available: + +``` +> status +``` + +Or programmatically via the `` message capabilities received during +connection establishment. + +### Get Entire Running Configuration + +Useful for exploration or backup: + +```xml + + + + + + + +``` + +Using netopeer2-cli: + +``` +> get-config --source running +``` + +### Common Workflow Patterns + +#### Pattern 1: Find interface by IP address + +Get all interfaces with their IPs, then filter: + +``` +> get --filter-xpath /interfaces +``` + +Parse the XML output to find which interface has the desired IP. + +#### Pattern 2: Check which interfaces are down + +``` +> get --filter-xpath /interfaces/interface/oper-status +``` + +Look for interfaces with `down`. + +#### Pattern 3: Get interface statistics for monitoring + +```xml + + + + + + + + + + + +``` + +Returns in-octets, out-octets, in-errors, out-errors for all interfaces. + +## Scripting with netconf-client + +[netconf-client](https://github.com/wires-se/netconf-client) is a lightweight +Python-based NETCONF client designed for scripting and automation. + +### Installation + +```bash +~$ pip install netconf-client +``` + +Or clone and install from source: + +```bash +~$ git clone https://github.com/wires-se/netconf-client.git +~$ cd netconf-client +~$ pip install . +``` + +### Basic Usage + +The client provides a simple command-line interface: + +```bash +~$ netconf-client --host example.local --user admin --password admin +``` + +Common operations: + +- `get-config` - Retrieve configuration +- `edit-config` - Modify configuration +- `get` - Retrieve operational state +- `copy-config` - Copy between datastores +- `lock/unlock` - Lock datastores +- `commit` - Commit candidate configuration + +### Python API + +You can also use netconf-client as a Python library: + +```python +from netconf_client.client import NetconfClient + +# Connect +client = NetconfClient( + host='example.local', + username='admin', + password='admin' +) + +# Get configuration +config = client.get_config(source='running') +print(config) + +# Edit configuration +xml_config = """ + + + newhostname + + +""" +client.edit_config(target='candidate', config=xml_config) +client.commit() + +# Close connection +client.close() +``` + +## Configuration Examples + +### Read Hostname + +**XML request:** + +```xml + + + + + + + + + + + + +``` + +**Using netopeer2-cli:** + +``` +> get-config --source running --filter-xpath /system/hostname +``` + +**Using netconf-client:** + +```bash +~$ netconf-client --host example.local --user admin \ + get-config --source running --xpath /system/hostname +``` + +**Response:** + +```xml + + + + example + + + +``` + +### Set Hostname + +**XML request:** + +```xml + + + + + + + + newhostname + + + + +``` + +**Using netopeer2-cli:** + +Save the config to `/tmp/hostname.xml`: + +```xml + + + newhostname + + +``` + +Then apply: + +``` +> edit-config --target candidate --config=/tmp/hostname.xml +> commit +``` + +**Using netconf-client:** + +```bash +~$ cat > hostname.xml < + + newhostname + + +EOF + +~$ netconf-client --host example.local --user admin \ + edit-config --target candidate --config hostname.xml + +~$ netconf-client --host example.local --user admin commit +``` + +### Add IP Address to Interface + +Save the config to `ip-config.xml`: + +```xml + + + + eth0 + +
+ 192.168.1.100 + 24 +
+
+
+
+
+``` + +**Using netconf-client:** + +```bash +~$ netconf-client --host example.local --user admin \ + edit-config --target candidate --config ip-config.xml +~$ netconf-client --host example.local --user admin commit +``` + +### Copy Running to Startup + +**XML request:** + +```xml + + + + + + + + + + +``` + +**Using netopeer2-cli:** + +``` +> copy-config --source running --target startup +``` + +**Using netconf-client:** + +```bash +~$ netconf-client --host example.local --user admin \ + copy-config --source running --target startup +``` + +## Operational Data Examples + +### Read Interface State + +**XML request:** + +```xml + + + + + + eth0 + + + + + +``` + +**Using netopeer2-cli:** + +``` +> get --filter-xpath /interfaces/interface[name='eth0'] +``` + +**Using netconf-client:** + +```bash +~$ netconf-client --host example.local --user admin \ + get --xpath "/interfaces/interface[name='eth0']" +``` + +This returns operational state including admin/oper status, statistics, +MAC address, MTU, and IP addresses. + +### Read All Interfaces + +**Using netopeer2-cli:** + +``` +> get --filter-xpath /interfaces +``` + +**Using netconf-client:** + +```bash +~$ netconf-client --host example.local --user admin \ + get --xpath /interfaces +``` + +### Read Routing Table + +**Using netconf-client:** + +```bash +~$ netconf-client --host example.local --user admin \ + get --xpath "/routing/ribs/rib[name='ipv4-default']" +``` + +### Read OSPF Neighbors + +**Using netconf-client:** + +```bash +~$ netconf-client --host example.local --user admin \ + get --xpath "/routing/control-plane-protocols/control-plane-protocol[type='ietf-ospf:ospfv2'][name='default']/ietf-ospf:ospf" +``` + +## Advanced Scripting + +### Python Script: Backup Configuration + +```python +#!/usr/bin/env python3 +from netconf_client.client import NetconfClient +from datetime import datetime +import sys + +def backup_config(host, user, password, output_file): + try: + # Connect + client = NetconfClient(host=host, username=user, password=password) + + # Get running config + config = client.get_config(source='running') + + # Save to file with timestamp + timestamp = datetime.now().strftime('%Y%m%d-%H%M%S') + filename = f"{output_file}-{timestamp}.xml" + + with open(filename, 'w') as f: + f.write(config) + + print(f"Configuration backed up to {filename}") + + client.close() + return 0 + + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + return 1 + +if __name__ == '__main__': + if len(sys.argv) != 5: + print(f"Usage: {sys.argv[0]} ") + sys.exit(1) + + sys.exit(backup_config(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])) +``` + +Usage: + +```bash +~$ chmod +x backup.py +~$ ./backup.py example.local admin admin config-backup +Configuration backed up to config-backup-20250102-143022.xml +``` + +### Python Script: Monitor Interface Statistics + +```python +#!/usr/bin/env python3 +from netconf_client.client import NetconfClient +import xml.etree.ElementTree as ET +import time +import sys + +def get_interface_stats(client, interface): + """Get interface statistics""" + xpath = f"/interfaces/interface[name='{interface}']/statistics" + data = client.get(filter_xpath=xpath) + + # Parse XML to extract counters + root = ET.fromstring(data) + ns = {'if': 'urn:ietf:params:xml:ns:yang:ietf-interfaces'} + + stats = {} + for stat in root.findall('.//if:statistics/*', ns): + stats[stat.tag.split('}')[1]] = int(stat.text) + + return stats + +def monitor_interface(host, user, password, interface, interval=5): + """Monitor interface statistics""" + client = NetconfClient(host=host, username=user, password=password) + + print(f"Monitoring {interface} on {host} (Ctrl-C to stop)") + print(f"{'Time':<20} {'RX Packets':<15} {'TX Packets':<15} {'RX Bytes':<15} {'TX Bytes':<15}") + print("-" * 80) + + try: + while True: + stats = get_interface_stats(client, interface) + timestamp = time.strftime('%Y-%m-%d %H:%M:%S') + + print(f"{timestamp:<20} " + f"{stats.get('in-unicast-pkts', 0):<15} " + f"{stats.get('out-unicast-pkts', 0):<15} " + f"{stats.get('in-octets', 0):<15} " + f"{stats.get('out-octets', 0):<15}") + + time.sleep(interval) + + except KeyboardInterrupt: + print("\nMonitoring stopped") + finally: + client.close() + +if __name__ == '__main__': + if len(sys.argv) < 5: + print(f"Usage: {sys.argv[0]} [interval]") + sys.exit(1) + + interval = int(sys.argv[5]) if len(sys.argv) > 5 else 5 + monitor_interface(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], interval) +``` + +Usage: + +```bash +~$ chmod +x monitor.py +~$ ./monitor.py example.local admin admin eth0 2 +Monitoring eth0 on example.local (Ctrl-C to stop) +Time RX Packets TX Packets RX Bytes TX Bytes +-------------------------------------------------------------------------------- +2025-01-02 14:35:10 12453 8932 1847392 892341 +2025-01-02 14:35:12 12489 8967 1851204 895673 +... +``` + +### Shell Script: Batch Configuration + +```bash +#!/bin/bash +# Apply configuration to multiple devices + +DEVICES="device1.local device2.local device3.local" +USER="admin" +PASSWORD="admin" +CONFIG_FILE="$1" + +if [ -z "$CONFIG_FILE" ]; then + echo "Usage: $0 " + exit 1 +fi + +for device in $DEVICES; do + echo "Configuring $device..." + + # Edit candidate + netconf-client --host "$device" --user "$USER" --password "$PASSWORD" \ + edit-config --target candidate --config "$CONFIG_FILE" + + if [ $? -eq 0 ]; then + # Commit if edit succeeded + netconf-client --host "$device" --user "$USER" --password "$PASSWORD" commit + echo " ✓ $device configured successfully" + else + echo " ✗ $device configuration failed" + fi +done +``` + +## Other NETCONF Tools + +### ncclient (Python) + +Popular Python library for NETCONF: + +```bash +~$ pip install ncclient +``` + +Example: + +```python +from ncclient import manager + +with manager.connect(host='example.local', port=830, + username='admin', password='admin', + hostkey_verify=False) as m: + # Get config + c = m.get_config(source='running') + print(c) +``` + +### Ansible + +Ansible includes NETCONF modules for automation: + +```yaml +- name: Get interface config + netconf_get: + source: running + filter: +``` + +### Cisco Tools + +- **NSO (Network Services Orchestrator)**: Enterprise orchestration platform +- **YANG Suite**: Web-based YANG exploration and testing tool +- **Cisco pyATS**: Network test automation + +## Troubleshooting + +### Enable NETCONF Debugging + +For netconf-client, use verbose mode: + +```bash +~$ netconf-client --host example.local --user admin --verbose get-config +``` + +For netopeer2-cli, enable debug output: + +``` +> debug 1 +> get-config --source running +``` + +### Common Issues + +**Connection refused:** + +- Verify SSH is running on port 830: `ssh -p 830 admin@example.local` +- Check firewall rules + +**Authentication failed:** + +- Verify credentials +- Check user has NETCONF access permissions + +**Operation not supported:** + +- Verify NETCONF capability: `netopeer2-cli` → `status` → check capabilities +- Some operations require specific YANG modules + +## References + +- [NETCONF Protocol (RFC 6241)](https://datatracker.ietf.org/doc/html/rfc6241) +- [netconf-client on GitHub](https://github.com/wires-se/netconf-client) +- [netopeer2 Documentation](https://github.com/CESNET/netopeer2) +- [YANG Data Modeling Language (RFC 7950)](https://datatracker.ietf.org/doc/html/rfc7950) +- [ietf-interfaces YANG module](https://datatracker.ietf.org/doc/html/rfc8343) +- [ietf-system YANG module](https://datatracker.ietf.org/doc/html/rfc7317) +- [ncclient Documentation](https://ncclient.readthedocs.io/) diff --git a/doc/scripting-restconf.md b/doc/scripting-restconf.md index 3a7c07e25..567c44427 100644 --- a/doc/scripting-restconf.md +++ b/doc/scripting-restconf.md @@ -1,46 +1,149 @@ -# Examples using RESTCONF +# Scripting with RESTCONF -## Factory Reset +RESTCONF provides a programmatic interface to both configuration and +operational data over HTTPS. This guide shows practical examples using +`curl` to interact with the RESTCONF API. +All examples use the following conventions: + +- **Host**: `example.local` (replace with your device hostname/IP) +- **Credentials**: `admin:admin` (default username:password) +- **HTTPS**: Self-signed certificates require `-k` flag in curl + +## Helper Script + +To simplify RESTCONF operations, create a `curl.sh` wrapper script: + +```bash +#!/bin/sh + +AUTH=${AUTH:-admin:admin} +HOST=${HOST:-infix.local} + +method=$1 +path=$2 +shift 2 + +set -x +exec curl \ + --insecure \ + --user ${AUTH} \ + --request ${method} \ + --header "Content-Type: application/yang-data+json" \ + --header "Accept: application/yang-data+json" \ + "$@" \ + https://${HOST}/restconf/ds/ietf-datastores:${path} ``` -~$ curl -kX POST -u admin:admin \ - -H "Content-Type: application/yang-data+json" \ - https://example.local/restconf/operations/ietf-factory-default:factory-reset -curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 + +Make it executable: + +```bash +~$ chmod +x curl.sh ``` -## System Reboot +This wrapper handles authentication, headers, and the base URL construction, +making commands much cleaner. You can override defaults with environment +variables: +```bash +~$ HOST=192.168.1.10 AUTH=admin:secret ./curl.sh GET running/... ``` -~$ curl -kX POST -u admin:admin \ - -H "Content-Type: application/yang-data+json" \ - https://example.local/restconf/operations/ietf-system:system-restart + +The examples below show both raw `curl` commands and the equivalent using +`curl.sh` where applicable. + +## Discovery & Common Patterns + +Before working with specific configuration items, you often need to discover +what exists on the system. This section shows common discovery patterns and +practical workflows. + +### Discovering Available Interfaces + +**List all interface names:** + +```bash +~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null | jq -r '.["ietf-interfaces:interfaces"]["interface"][].name' +lo +e0 +e1 ``` -## Set Date and Time +This is essential for automation - interface names vary by platform (eth0, +e1, enp0s3, etc.), so scripts should discover them rather than hardcode. + +### Get API Capabilities -Here's an example of an RPC that takes input/argument: +Discover what YANG modules are available: +```bash +~$ curl -kX GET -u admin:admin \ + -H 'Accept: application/yang-data+json' \ + https://example.local/restconf/data/ietf-yang-library:yang-library ``` -~$ curl -kX POST -u admin:admin \ - -H "Content-Type: application/yang-data+json" \ - -d '{"ietf-system:input": {"current-datetime": "2024-04-17T13:48:02-01:00"}}' \ - https://example.local/restconf/operations/ietf-system:set-current-datetime + +This returns all supported YANG modules, revisions, and features. + +### Get Entire Running Configuration + +Useful for exploration or backup: + +```bash +~$ ./curl.sh example.local GET running -o backup.json ``` -You can verify that the changes took by a remote SSH command: +### Common Workflow Patterns + +#### Pattern 1: Find interface by IP address + +Get all interfaces with IPs and search: +```bash +~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \ + | jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["ietf-ip:ipv4"]["address"][]?.ip == "192.168.1.100") | .name' ``` -~$ ssh admin@example.local 'date' -Wed Apr 17 14:48:12 UTC 2024 -~$ + +#### Pattern 2: List all interfaces that are down + +```bash +~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \ + | jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["oper-status"] == "down") | .name' ``` -## Read Hostname +#### Pattern 3: Get statistics for all interfaces -Example of fetching JSON configuration data to stdout: +```bash +~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \ + | jq -r '.["ietf-interfaces:interfaces"]["interface"][] | "\(.name): RX \(.statistics["in-octets"]) TX \(.statistics["out-octets"])"' +``` +Output: + +``` +lo: RX 29320 TX 29320 +e0: RX 1847392 TX 892341 +e1: RX 0 TX 0 ``` + +#### Pattern 4: Check if interface exists before configuring + +```bash +~$ if ./curl.sh example.local GET running/ietf-interfaces:interfaces/interface=eth0 2>/dev/null | grep -q "ietf-interfaces:interface"; then + echo "Interface eth0 exists" + else + echo "Interface eth0 not found" + fi +``` + +## Configuration Operations + +### Read Hostname + +Example of fetching JSON configuration data: + +**Using curl directly:** + +```bash ~$ curl -kX GET -u admin:admin \ -H 'Accept: application/yang-data+json' \ https://example.local/restconf/data/ietf-system:system/hostname @@ -51,27 +154,68 @@ Example of fetching JSON configuration data to stdout: } ``` -## Set Hostname - -Example of inline JSON data: +**Using curl.sh:** +```bash +~$ ./curl.sh example.local GET running/ietf-system:system/hostname +{ + "ietf-system:system": { + "hostname": "foo" + } +} ``` + +### Set Hostname + +Example of updating configuration with inline JSON data: + +**Using curl directly:** + +```bash ~$ curl -kX PATCH -u admin:admin \ -H 'Content-Type: application/yang-data+json' \ -d '{"ietf-system:system":{"hostname":"bar"}}' \ https://example.local/restconf/data/ietf-system:system ``` -## Copy Running to Startup +**Using curl.sh:** + +```bash +~$ ./curl.sh example.local PATCH running/ietf-system:system \ + -d '{"ietf-system:system":{"hostname":"bar"}}' +``` + +### Add IP Address to Interface + +Add an IP address to the loopback interface: + +```bash +~$ ./curl.sh example.local POST \ + running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \ + -d '{ "prefix-length": 32 }' +``` + +### Delete IP Address from Interface + +Remove an IP address from the loopback interface: + +```bash +~$ ./curl.sh example.local DELETE \ + running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 +``` + +### Copy Running to Startup No copy command available yet to copy between datastores, and the Rousette back-end also does not support "write-through" to the startup datastore. -To save running-config to startup-config, use the following example to -fetch running to a local file and then update startup with it: +To save running-config to startup-config, fetch running to a local file +and then update startup with it: -``` +**Using curl directly:** + +```bash ~$ curl -kX GET -u admin:admin -o running-config.json \ -H 'Accept: application/yang-data+json' \ https://example.local/restconf/ds/ietf-datastores:running @@ -80,3 +224,194 @@ fetch running to a local file and then update startup with it: -H 'Content-Type: application/yang-data+json' \ https://example.local/restconf/ds/ietf-datastores:startup ``` + +**Using curl.sh:** + +```bash +~$ ./curl.sh example.local GET running -o running-config.json +~$ ./curl.sh example.local PUT startup -d @running-config.json +``` + +## Operational Data + +### Read Interface Configuration + +Get the running configuration for the loopback interface: + +```bash +~$ ./curl.sh example.local GET running/ietf-interfaces:interfaces/interface=lo +``` + +### Read Interface Operational State + +Get operational data (state, statistics, etc.) for an interface: + +```bash +~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces/interface=lo +``` + +This includes administrative and operational state, MAC address, MTU, and +statistics counters. + +### Read Interface Statistics + +Extract specific statistics using `jq`: + +```bash +~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces/interface=eth0 2>/dev/null \ + | jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]' +``` + +### List All Interfaces + +Get operational data for all interfaces: + +```bash +~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces +``` + +### Read Routing Table + +Get the IPv4 routing table: + +```bash +~$ ./curl.sh example.local GET operational/ietf-routing:routing/ribs/rib=ipv4-default +``` + +### Read OSPF State + +Get OSPF operational data (neighbors, routes, etc.): + +```bash +~$ ./curl.sh example.local GET operational/ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default +``` + +Or get just the neighbor information: + +```bash +~$ ./curl.sh example.local GET operational/ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default/ietf-ospf:ospf/areas/area=0.0.0.0/interfaces +``` + +## System Operations (RPCs) + +### Factory Reset + +Reset the system to factory defaults: + +```bash +~$ curl -kX POST -u admin:admin \ + -H "Content-Type: application/yang-data+json" \ + https://example.local/restconf/operations/ietf-factory-default:factory-reset +curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 +``` + +> **Note:** The connection error is expected - the device resets immediately. + +### System Reboot + +Reboot the system: + +```bash +~$ curl -kX POST -u admin:admin \ + -H "Content-Type: application/yang-data+json" \ + https://example.local/restconf/operations/ietf-system:system-restart +``` + +### Set Date and Time + +Example of an RPC that takes input/arguments: + +```bash +~$ curl -kX POST -u admin:admin \ + -H "Content-Type: application/yang-data+json" \ + -d '{"ietf-system:input": {"current-datetime": "2024-04-17T13:48:02-01:00"}}' \ + https://example.local/restconf/operations/ietf-system:set-current-datetime +``` + +Verify the change with SSH: + +```bash +~$ ssh admin@example.local 'date' +Wed Apr 17 14:48:12 UTC 2024 +``` + +## Advanced Examples + +### Makefile for Common Operations + +Create a `Makefile` to simplify common operations: + +```makefile +HOST ?= infix.local + +lo-running: + ./curl.sh $(HOST) GET running/ietf-interfaces:interfaces/interface=lo + +lo-operational: + ./curl.sh $(HOST) GET operational/ietf-interfaces:interfaces/interface=lo + +lo-add-ip: + ./curl.sh $(HOST) POST \ + running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \ + -d '{ "prefix-length": 32 }' + +lo-del-ip: + ./curl.sh $(HOST) DELETE \ + running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 + +%-stats: + @./curl.sh $(HOST) GET operational/ietf-interfaces:interfaces/interface=$* 2>/dev/null \ + | jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]' + +%-monitor: + while sleep 0.2; do make -s HOST=$(HOST) $*-stats; done \ + | ttyplot -t "$(HOST):$* in-octets" -r +``` + +Usage examples: + +```bash +# Get loopback operational state +~$ make lo-operational + +# Add IP to loopback +~$ make lo-add-ip + +# Get eth0 statistics +~$ make eth0-stats + +# Monitor eth0 traffic in real-time (requires ttyplot) +~$ make eth0-monitor +``` + +You can override the host: + +```bash +~$ make HOST=192.168.1.10 lo-operational +``` + +### Monitoring Interface Traffic + +The `%-monitor` target demonstrates real-time monitoring by polling +interface statistics and piping to `ttyplot` for visualization. Install +`ttyplot` with: + +```bash +~$ sudo apt install ttyplot +``` + +Then monitor any interface: + +```bash +~$ make eth0-monitor +``` + +This creates a live ASCII graph of incoming octets on `eth0`. + +## References + +- [RESTCONF Protocol (RFC 8040)](https://datatracker.ietf.org/doc/html/rfc8040) +- [YANG Data Modeling Language (RFC 7950)](https://datatracker.ietf.org/doc/html/rfc7950) +- [ietf-interfaces YANG module](https://datatracker.ietf.org/doc/html/rfc8343) +- [ietf-routing YANG module](https://datatracker.ietf.org/doc/html/rfc8349) +- [ietf-system YANG module](https://datatracker.ietf.org/doc/html/rfc7317) diff --git a/mkdocs.yml b/mkdocs.yml index 69a35d5c0..b4dfa86cd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -47,7 +47,8 @@ nav: - Introduction: scripting.md - Legacy Scripting: scripting-sysrepocfg.md - Production Testing: scripting-prod.md - - Remote RESTCONF: scripting-restconf.md + - With NETCONF: scripting-netconf.md + - With RESTCONF: scripting-restconf.md - Developer's Corner: - Branding & Releases: branding.md - Developer's Guide: developers-guide.md