š 3.7 DevNet Resources for Different Scenarios
What is Cisco DevNet?
Cisco DevNet is Cisco's developer program providing resources, tools, sandboxes, and community support for developers working with Cisco technologies.
https://developer.cisco.comAccess: Free registration (DevNet account)
1. DevNet Sandbox
Sandbox Free Lab Environments
DevNet Sandboxes provide free, hands-on access to Cisco platforms and APIs for testing and learning without requiring physical equipment.
Types of Sandboxes
| Sandbox Type | Description | Access |
|---|---|---|
| Always-On | Shared environment, immediately available | Instant, no reservation |
| Reservation-Based | Private environment, dedicated resources | Reserve up to 1 week |
Available Sandboxes (Examples)
- Meraki Always-On: Test Meraki Dashboard API
- DNA Center: Explore intent-based networking APIs
- IOS XE (CSR1000v): Practice NETCONF/RESTCONF
- NX-OS (Nexus 9000v): Test NX-API and NETCONF
- Webex: Build bots and integrations
- ACI: Test APIC REST API
- SD-WAN: Explore vManage API
- Intersight: Cloud compute management
š Scenario: When to Use Sandbox
- Testing API calls: Before production implementation
- Learning new platform: Hands-on practice without hardware
- Proof of Concept (POC): Validate automation ideas
- Training: Practice for DEVASC exam
- Development: Develop and test scripts safely
2. Code Exchange
Code Exchange Community Code Repository
Code Exchange is a repository of community-contributed code samples, scripts, and applications for Cisco technologies.
What You'll Find
- Sample Scripts: Python, JavaScript, Go examples
- Complete Applications: Ready-to-use tools
- API Examples: Code for various Cisco APIs
- Automation Tools: Network automation utilities
- Integration Examples: Third-party integrations
š Scenario: When to Use Code Exchange
- Need code examples: Find working implementations
- Starting a project: Use as template or reference
- Learning API usage: See real-world code patterns
- Contributing: Share your own code with community
- Avoid reinventing: Find existing solutions
3. Learning Labs
Learning Labs Interactive Tutorials
Learning Labs provide step-by-step, hands-on tutorials with integrated sandbox environments for learning Cisco technologies.
Features
- Guided Tutorials: Step-by-step instructions
- Integrated Sandbox: Lab environment built-in
- Progressive Learning: Beginner to advanced tracks
- Learning Tracks: Organized curriculum paths
- Certifications: DEVASC exam preparation
š Scenario: When to Use Learning Labs
- New to topic: Start with guided learning
- Exam preparation: DEVASC study materials
- Structured learning: Follow learning tracks
- Hands-on practice: Interactive exercises
- Skill validation: Complete labs to earn badges
4. API Documentation
API Docs Technical Reference
API Documentation provides comprehensive technical references for all Cisco APIs including endpoints, parameters, examples, and SDKs.
Documentation Features
- API Reference: Complete endpoint documentation
- Interactive Console: Try API calls in browser
- Code Samples: Python, JavaScript examples
- SDK Documentation: Library references
- Authentication Guides: How to authenticate
- Rate Limits: Usage quotas and limits
š Scenario: When to Use API Documentation
- Implementing API calls: Reference for endpoints and parameters
- Troubleshooting errors: Check expected responses
- Understanding capabilities: What API can do
- Version compatibility: API version differences
- SDK usage: Method references and examples
5. Support and Forums
Support Community Help
DevNet Support Channels
| Resource | Purpose | URL |
|---|---|---|
| DevNet Community Forums | Ask questions, share knowledge | https://community.cisco.com/devnet |
| DevNet Support | Technical support for DevNet services | https://developer.cisco.com/site/support |
| GitHub Discussions | SDK-specific issues and discussions | GitHub repositories |
| Stack Overflow | Programming questions (tag: cisco-devnet) | https://stackoverflow.com |
š Scenario: When to Use Support/Forums
- Stuck on issue: Get community help
- API bugs: Report and track issues
- Best practices: Learn from others' experiences
- Feature requests: Suggest improvements
- SDK errors: Troubleshoot with maintainers
Quick Reference: Choose the Right Resource
| Your Need | Best Resource | Why |
|---|---|---|
| Test API without equipment | Sandbox | Free lab access, always available |
| Find working code example | Code Exchange | Community-contributed samples |
| Learn new technology | Learning Labs | Guided, hands-on tutorials |
| API endpoint reference | API Documentation | Complete technical reference |
| Troubleshooting help | Forums/Support | Community and expert assistance |
| DEVASC exam prep | Learning Labs | Certification-focused content |
| SDK documentation | API Docs + GitHub | Method references and examples |
- Start with Learning Labs: Get structured introduction
- Use Sandboxes: Always test in sandbox before production
- Check Code Exchange: Don't reinvent the wheel
- Read API Docs: Official source for accurate information
- Engage Community: Forums are valuable for troubleshooting
- Give Back: Share your code and help others
š 3.8 Model-Driven Programmability (YANG, RESTCONF, NETCONF)
What is Model-Driven Programmability?
Model-driven programmability uses standardized data models (YANG) to represent network device configuration and state, accessed through structured protocols (NETCONF/RESTCONF) instead of CLI scraping.
1. YANG (Yet Another Next Generation)
YANG Data Modeling Language
YANG is a data modeling language used to model configuration and operational data for network devices. It defines the structure, syntax, and semantics of data.
YANG Model Structure
// YANG Model Example (simplified)
module ietf-interfaces {
namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
prefix if;
container interfaces {
list interface {
key "name";
leaf name {
type string;
description "Interface name";
}
leaf description {
type string;
description "Interface description";
}
leaf enabled {
type boolean;
default true;
description "Interface admin status";
}
leaf type {
type identityref {
base interface-type;
}
description "Interface type";
}
}
}
}
YANG Model Types
| Model Category | Description | Examples |
|---|---|---|
| IETF Models | Standard industry models from IETF | ietf-interfaces ietf-ip ietf-routing |
| OpenConfig | Vendor-neutral models | openconfig-interfaces openconfig-bgp openconfig-vlan |
| Cisco Native | Cisco-specific features | Cisco-IOS-XE-native Cisco-NX-OS-device |
- pyang: Validate and convert YANG models
- YANG Suite: Web-based YANG explorer
- Device YANG Models:
show platform software yang-management
2. NETCONF (Network Configuration Protocol)
NETCONF Configuration Management Protocol
NETCONF is an IETF standard protocol for network device configuration management using XML encoding over SSH.
Key Features
- Transport: SSH (port 830), TLS, SOAP
- Encoding: XML
- Operations: get, get-config, edit-config, delete-config
- Datastores: running, candidate, startup
- Transactions: Atomic operations with rollback
- Validation: Pre-commit validation
NETCONF Operations
| Operation | Purpose | Example Use |
|---|---|---|
| <get> | Retrieve config + operational data | Get interface stats and config |
| <get-config> | Retrieve configuration only | Get running/candidate config |
| <edit-config> | Modify configuration | Configure interfaces, routing |
| <copy-config> | Copy between datastores | Copy candidate to running |
| <delete-config> | Delete configuration | Clear startup config |
| <lock>/<unlock> | Lock datastore | Prevent concurrent changes |
Python NETCONF Example
#!/usr/bin/env python3
"""
NETCONF Complete Example
Demonstrates all major operations
"""
from ncclient import manager
import xml.dom.minidom
# Connect to device
def netconf_connect(host, username, password):
"""Establish NETCONF session"""
device = {
'host': host,
'port': 830,
'username': username,
'password': password,
'hostkey_verify': False,
'device_params': {'name': 'iosxe'}
}
conn = manager.connect(**device)
print(f"ā
NETCONF connected to {host}")
return conn
# Get capabilities
def get_capabilities(conn):
"""List device YANG capabilities"""
print("\n" + "="*70)
print("DEVICE CAPABILITIES")
print("="*70)
for capability in conn.server_capabilities:
if 'ietf-interfaces' in capability:
print(f"ā
{capability}")
# Get configuration
def get_running_config(conn):
"""Get running configuration"""
config = conn.get_config(source='running')
# Pretty print XML
xml_str = xml.dom.minidom.parseString(str(config)).toprettyxml()
print("\nā
Running configuration retrieved")
return config
# Get interface using filter
def get_interface_config(conn, interface_name):
"""Get specific interface configuration"""
filter_xml = f"""
{interface_name}
"""
result = conn.get(filter=filter_xml)
print(f"\nā
Retrieved {interface_name} configuration")
return result
# Configure interface
def configure_interface(conn, intf_name, description, enabled=True):
"""Configure interface using edit-config"""
config_xml = f"""
{intf_name}
{description}
{str(enabled).lower()}
"""
# Edit configuration
response = conn.edit_config(
target='running',
config=config_xml
)
print(f"ā
Interface {intf_name} configured via NETCONF")
return response
# Use candidate configuration (safer)
def configure_with_candidate(conn, config_xml):
"""Use candidate datastore with validation"""
# Lock candidate config
conn.lock(target='candidate')
print("š Candidate config locked")
try:
# Edit candidate
conn.edit_config(target='candidate', config=config_xml)
print("ā
Changes staged in candidate")
# Validate
conn.validate(source='candidate')
print("ā
Configuration validated")
# Commit to running
conn.commit()
print("ā
Configuration committed to running")
except Exception as e:
print(f"ā Error: {e}")
# Discard changes
conn.discard_changes()
print("ā ļø Changes discarded")
finally:
# Unlock
conn.unlock(target='candidate')
print("š Candidate config unlocked")
# Main execution
if __name__ == "__main__":
conn = netconf_connect('ios-xe.example.com', 'admin', 'cisco')
# Get capabilities
get_capabilities(conn)
# Configure interface
configure_interface(
conn,
'GigabitEthernet1',
'Configured via NETCONF',
enabled=True
)
# Close session
conn.close_session()
print("\nā
NETCONF session closed")
3. RESTCONF
RESTCONF RESTful Network Configuration
RESTCONF provides a RESTful API interface to YANG data models, using HTTP methods and JSON/XML encoding.
Key Features
- Transport: HTTPS (port 443)
- Encoding: JSON or XML
- Methods: GET, POST, PUT, PATCH, DELETE
- RESTful: Uses standard REST principles
- Easier: Simpler than NETCONF for developers
RESTCONF vs NETCONF
| Feature | NETCONF | RESTCONF |
|---|---|---|
| Transport | SSH (port 830) | HTTPS (port 443) |
| Encoding | XML only | JSON or XML |
| Protocol | RPC-based | RESTful |
| Operations | XML RPC operations | HTTP methods (GET, POST, etc.) |
| Session | Persistent SSH session | Stateless HTTP |
| Candidate Config | ā Full support | ā ļø Limited |
| Ease of Use | ā ļø More complex | ā Simpler (REST) |
RESTCONF URL Structure
# RESTCONF URL Format
https://{device}/restconf/data/{yang-module}:{container}/{list-entry}
# Examples:
# Get all interfaces
GET https://ios-xe/restconf/data/ietf-interfaces:interfaces
# Get specific interface
GET https://ios-xe/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet1
# Get IP configuration
GET https://ios-xe/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet1/ietf-ip:ipv4
# Configure interface (PATCH)
PATCH https://ios-xe/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet1
Body: {"ietf-interfaces:interface": {"description": "Updated via RESTCONF"}}
# Create new configuration (POST)
POST https://ios-xe/restconf/data/ietf-interfaces:interfaces
Body: {"ietf-interfaces:interface": {"name": "Loopback100", "type": "softwareLoopback"}}
# Delete configuration (DELETE)
DELETE https://ios-xe/restconf/data/ietf-interfaces:interfaces/interface=Loopback100
Python RESTCONF Example
#!/usr/bin/env python3
"""
RESTCONF Complete Example
Demonstrates CRUD operations on IOS XE
"""
import requests
import json
from requests.auth import HTTPBasicAuth
import urllib3
urllib3.disable_warnings()
class RESTCONFClient:
"""RESTCONF API Client for IOS XE"""
def __init__(self, host, username, password):
self.base_url = f"https://{host}/restconf/data"
self.auth = HTTPBasicAuth(username, password)
self.headers = {
'Accept': 'application/yang-data+json',
'Content-Type': 'application/yang-data+json'
}
def get_interfaces(self):
"""GET - Retrieve all interfaces"""
url = f"{self.base_url}/ietf-interfaces:interfaces"
response = requests.get(
url,
auth=self.auth,
headers=self.headers,
verify=False
)
if response.status_code == 200:
data = response.json()
interfaces = data['ietf-interfaces:interfaces']['interface']
print("="*70)
print("INTERFACES")
print("="*70)
for intf in interfaces:
print(f"\n{intf['name']}")
print(f" Type: {intf['type']}")
print(f" Enabled: {intf.get('enabled', 'N/A')}")
print(f" Description: {intf.get('description', 'None')}")
return interfaces
else:
print(f"ā Error: {response.status_code}")
return []
def get_interface(self, name):
"""GET - Retrieve specific interface"""
url = f"{self.base_url}/ietf-interfaces:interfaces/interface={name}"
response = requests.get(
url,
auth=self.auth,
headers=self.headers,
verify=False
)
if response.status_code == 200:
intf = response.json()['ietf-interfaces:interface']
print(f"\nā
Interface {name}:")
print(f" Type: {intf['type']}")
print(f" Admin Status: {'Up' if intf.get('enabled', False) else 'Down'}")
return intf
return None
def create_loopback(self, number, description, ip_address, subnet_mask):
"""POST - Create new loopback interface"""
url = f"{self.base_url}/ietf-interfaces:interfaces"
data = {
"ietf-interfaces:interface": {
"name": f"Loopback{number}",
"description": description,
"type": "iana-if-type:softwareLoopback",
"enabled": True,
"ietf-ip:ipv4": {
"address": [
{
"ip": ip_address,
"netmask": subnet_mask
}
]
}
}
}
response = requests.post(
url,
auth=self.auth,
headers=self.headers,
json=data,
verify=False
)
if response.status_code == 201:
print(f"ā
Loopback{number} created: {ip_address}")
return True
else:
print(f"ā Error: {response.status_code} - {response.text}")
return False
def update_interface(self, name, description=None, enabled=None):
"""PATCH - Partially update interface"""
url = f"{self.base_url}/ietf-interfaces:interfaces/interface={name}"
data = {"ietf-interfaces:interface": {}}
if description:
data["ietf-interfaces:interface"]["description"] = description
if enabled is not None:
data["ietf-interfaces:interface"]["enabled"] = enabled
response = requests.patch(
url,
auth=self.auth,
headers=self.headers,
json=data,
verify=False
)
if response.status_code in [200, 204]:
print(f"ā
Interface {name} updated")
return True
else:
print(f"ā Error: {response.status_code}")
return False
def delete_interface(self, name):
"""DELETE - Remove interface"""
url = f"{self.base_url}/ietf-interfaces:interfaces/interface={name}"
response = requests.delete(
url,
auth=self.auth,
headers=self.headers,
verify=False
)
if response.status_code in [200, 204]:
print(f"ā
Interface {name} deleted")
return True
else:
print(f"ā Error: {response.status_code}")
return False
# Usage Example
if __name__ == "__main__":
client = RESTCONFClient('ios-xe.example.com', 'admin', 'cisco')
# READ - Get all interfaces
client.get_interfaces()
# CREATE - Add loopback
client.create_loopback(100, 'Test Loopback', '10.1.1.1', '255.255.255.255')
# UPDATE - Modify description
client.update_interface('Loopback100', description='Updated via RESTCONF')
# DELETE - Remove loopback
client.delete_interface('Loopback100')
Model-Driven vs Traditional CLI
| Aspect | Traditional CLI | Model-Driven (NETCONF/RESTCONF) |
|---|---|---|
| Data Structure | Unstructured text | Structured (JSON/XML) |
| Parsing | Screen scraping, regex | Direct object access |
| Validation | After execution | Before commit (YANG schema) |
| Transactions | No rollback | Atomic with rollback |
| Vendor Neutral | Vendor-specific syntax | Standard models (IETF, OpenConfig) |
| Error Handling | Parse error messages | Structured error responses |
| Best For | Quick changes, troubleshooting | Automation, programmability |
- Standardization: YANG models provide consistent structure
- Validation: Schema validation before applying changes
- Transactions: Atomic operations with rollback capability
- No Parsing: Structured data eliminates screen scraping
- Vendor Neutral: Same models work across vendors
- API Evolution: Models version independently from device OS
- NETCONF: When you need transactional safety, candidate config, or complex operations
- RESTCONF: When you prefer REST, simpler integration, or working with web apps
- Both use YANG: Same data models, different access methods
š Interactive Python Interpreter
- Write Python code in the editor below
- Click "ā¶ Run Code" to execute
- Experiment with DevNet resource scenarios
- Learn YANG model concepts