šŸŽ“ DevNet Resources & Programmability

DevNet Ecosystem and Model-Driven Configuration

šŸŽ“ 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.

🌐 DevNet Website: https://developer.cisco.com
Access: Free registration (DevNet account)
graph TD A["DevNet Resources"] --> B["Sandbox"] A --> C["Code Exchange"] A --> D["Learning Labs"] A --> E["API Docs"] A --> F["Support"] A --> G["Forums"] B --> B1["Free Lab Access"] C --> C1["Code Samples"] D --> D1["Guided Tutorials"] E --> E1["API Reference"] F --> F1["Technical Help"] G --> G1["Community"] style A fill:#667eea,stroke:#764ba2,stroke-width:3px,color:#fff style B fill:#66bb6a,stroke:#2e7d32,stroke-width:2px,color:#fff style C fill:#42a5f5,stroke:#1976d2,stroke-width:2px,color:#fff style D fill:#ffa726,stroke:#e65100,stroke-width:2px,color:#fff style E fill:#ab47bc,stroke:#6a1b9a,stroke-width:2px,color:#fff

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
šŸ“Œ Access Sandbox: https://devnetsandbox.cisco.com
šŸ“ 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
šŸ“Œ Access: https://developer.cisco.com/codeexchange
šŸ“ 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
šŸ“Œ Access: https://developer.cisco.com/learning
šŸ“ 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
šŸ“Œ Access: https://developer.cisco.com/docs
šŸ“ 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
āœ… Best Practices for Using DevNet:
  • 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.

graph LR A["Application"] --> B["NETCONF/RESTCONF"] B --> C["YANG Data Models"] C --> D["Device Configuration"] B --> E["Structured Protocol"] E --> E1["XML or JSON"] C --> F["Standardized Schema"] F --> F1["ietf-interfaces"] F --> F2["openconfig-bgp"] F --> F3["cisco-ios-xe-native"] style A fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000 style B fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#000 style C fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#000 style D fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#000

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
šŸ“Œ YANG Tools:
  • 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
āœ… Benefits of Model-Driven 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
šŸ’” When to Use Each Protocol:
  • 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

šŸ’” How to use:
  • Write Python code in the editor below
  • Click "ā–¶ Run Code" to execute
  • Experiment with DevNet resource scenarios
  • Learn YANG model concepts
šŸ“ Python Code Editor
⚔ Console Output
Ready to execute Python code...