<jupyter_start><jupyter_text>IOS-XE CLEU 2020 Demo  Connecting to a Device Let's define some variables:<jupyter_code># Local CSR 1000v (running under vagrant) -- rtr1
HOST = '127.0.0.1'
PORT = 2223
USER = 'vagrant'
PASS = '<PASSWORD>'<jupyter_output><empty_output><jupyter_text>Now let's establish a NETCONF session to that box using ncclient:<jupyter_code>from ncclient import manager
from lxml import etree

def pretty_print(retval):
        print(etree.tostring(retval.data, pretty_print=True).decode())

def my_unknown_host_cb(host, fingerprint):
    return True
    
m = manager.connect(host=HOST, port=PORT, username=USER, password=<PASSWORD>,
                    allow_agent=False,
                    look_for_keys=False,
                    hostkey_verify=False,
                    unknown_host_cb=my_unknown_host_cb)
m<jupyter_output><empty_output><jupyter_text>Capabilities Let's look at the capabilities presented by the thing we've just connected to:<jupyter_code>for c in m.server_capabilities:
    print(c)<jupyter_output>urn:ietf:params:netconf:base:1.0
urn:ietf:params:netconf:base:1.1
urn:ietf:params:netconf:capability:writable-running:1.0
urn:ietf:params:netconf:capability:xpath:1.0
urn:ietf:params:netconf:capability:validate:1.0
urn:ietf:params:netconf:capability:validate:1.1
urn:ietf:params:netconf:capability:rollback-on-error:1.0
urn:ietf:params:netconf:capability:notification:1.0
urn:ietf:params:netconf:capability:interleave:1.0
urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all-tagged
urn:ietf:params:netconf:capability:yang-library:1.0?revision=2016-06-21&module-set-id=61de1a2313e60afe62df413a77ed9087
http://tail-f.com/ns/netconf/actions/1.0
http://tail-f.com/ns/netconf/extensions
http://cisco.com/ns/cisco-xe-ietf-ip-deviation?module=cisco-xe-ietf-ip-deviation&revision=2016-08-10
http://cisco.com/ns/cisco-xe-ietf-ipv4-unicast-routing-deviation?module=cisco-xe-ietf-ipv4-unicast-routing-deviation&revision=2015-09-11
http://cisco.com/ns/cisco-xe-ietf-[...]<jupyter_text>Ok, that's a bit messy, so let's tidy it up a bit and look, initially, at all the base netconf capabilities:<jupyter_code>nc_caps = [c for c in m.server_capabilities if c.startswith('urn:ietf:params:netconf') and "smiv2" not in c]
for c in nc_caps:
    print(c)<jupyter_output>urn:ietf:params:netconf:base:1.0
urn:ietf:params:netconf:base:1.1
urn:ietf:params:netconf:capability:writable-running:1.0
urn:ietf:params:netconf:capability:xpath:1.0
urn:ietf:params:netconf:capability:validate:1.0
urn:ietf:params:netconf:capability:validate:1.1
urn:ietf:params:netconf:capability:rollback-on-error:1.0
urn:ietf:params:netconf:capability:notification:1.0
urn:ietf:params:netconf:capability:interleave:1.0
urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&also-supported=report-all-tagged
urn:ietf:params:netconf:capability:yang-library:1.0?revision=2016-06-21&module-set-id=61de1a2313e60afe62df413a77ed9087<jupyter_text>And now let's look at the capabilities that are related to model support:<jupyter_code>import re

for c in m.server_capabilities:
    model = re.search('module=([^&]*)&', c)
    if model is not None:
        print("{}".format(model.group(1)))

        revision = re.search('revision=([0-9]{4}-[0-9]{2}-[0-9]{2})', c)
        if revision is not None:
            print("  revision = {}".format(revision.group(1)))

        deviations = re.search('deviations=([a-zA-Z0-9\-,]+)($|&)',c)
        if deviations is not None:
            print("  deviations = {}".format(deviations.group(1)))

        features = re.search('features=([a-zA-Z0-9\-,]+)($|&)',c)
        if features is not None:
            print("  features = {}".format(features.group(1)))<jupyter_output><empty_output><jupyter_text>SchemaLet's take a look at playing with schema. First, we can try downloading them, picking one of the modules we got capabilities for.<jupyter_code># SCHEMA_TO_GET = 'openconfig-interfaces'
# SCHEMA_TO_GET = 'Cisco-IOS-XE-native'
# SCHEMA_TO_GET = 'Cisco-IOS-XE-features'
SCHEMA_TO_GET = 'Cisco-IOS-XE-interfaces-oper'

c = m.get_schema(SCHEMA_TO_GET)
print(c.data)<jupyter_output>module Cisco-IOS-XE-interfaces-oper {
  yang-version 1;
  namespace "http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper";
  prefix interfaces-ios-xe-oper;

  import ietf-inet-types {
    prefix inet;
  }
  import ietf-yang-types {
    prefix yang;
  }
  import cisco-semver {
    prefix cisco-semver;
  }

  organization
    "Cisco Systems, Inc.";
  contact
    "Cisco Systems, Inc.
     Customer Service
     
     Postal: 170 W Tasman Drive
     San Jose, CA 95134
     
     Tel: +1 1800 553-NETS
     
     E-mail: <EMAIL>";
  description
    "This module contains a collection of YANG definitions for
     monitoring the interfaces in a Network Element.
     Copyright (c) 2016-2019 by Cisco Systems, Inc.
     All rights reserved.";

  revision 2019-11-01 {
    description
      "- Added media type to interface
       - Added more interface speed values";
    reference "3.3.0";
    cisco-semver:module-version "3.3.0";
  }
  revision 2019-05-01 {
    description
      "- Added [...]<jupyter_text>That's not so readable. Let's use a utility called ```pyang``` to get something a bit more readable.<jupyter_code>from subprocess import Popen, PIPE, STDOUT

SCHEMA_TO_GET = 'Cisco-IOS-XE-interfaces-oper'

c = m.get_schema(SCHEMA_TO_GET)

# Simple pyang tree display
# p = Popen(['pyang', '-f', 'tree'], stdout=PIPE, stdin=PIPE, stderr=PIPE)

# Restrict display depth
# p = Popen(['pyang', '-f', 'tree', '--tree-depth', '2'], stdout=PIPE, stdin=PIPE, stderr=PIPE)

# Restrict display path
p = Popen(['pyang',
           '-f', 'tree',
           '--tree-path', 'interfaces/interface/statistics'],
          stdout=PIPE, stdin=PIPE, stderr=PIPE)

# Push the data from the get_schema through pyang
stdout_data = p.communicate(input=c.data.encode())[0]

print(stdout_data.decode())<jupyter_output><empty_output><jupyter_text>What About Config?The ncclient library provides for some simple operations. Let's skip thinking about schemas and stuff like that. Instead let's focus on config and getting end setting it. For that, ncclient provides two methods:* get_config - takes a target data store and an optional filter* edit_config - takes a target data store and an XML document with the edit request  Getting ConfigLet's look at some simple requests...<jupyter_code>c = m.get_config(source='running')
pretty_print(c)<jupyter_output><empty_output><jupyter_text>Now let's add in a simple filter:<jupyter_code>filter = '''
<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
 <username/>
</native>
'''

with m.locked(target='running'):
    c = m.get_config(source='running', filter=('subtree', filter))
    pretty_print(c)<jupyter_output><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <username>
      <name>vagrant</name>
      <privilege>15</privilege>
      <password>
        <encryption>0</encryption>
        <password><PASSWORD></password>
      </password>
    </username>
  </native>
</data><jupyter_text>Retrieve Interface Config Data (Native Model)<jupyter_code>filter = '''
<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <interface/>
</native>
'''
c = m.get_config(source='running', filter=('subtree', filter))
pretty_print(c)<jupyter_output><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <interface>
      <GigabitEthernet>
        <name>1</name>
        <ip>
          <address>
            <dhcp/>
          </address>
          <igmp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-igmp">
            <explicit-tracking>false</explicit-tracking>
            <proxy-service>false</proxy-service>
            <unidirectional-link>false</unidirectional-link>
            <v3lite>false</v3lite>
          </igmp>
        </ip>
        <mop>
          <enabled>false</enabled>
          <sysid>false</sysid>
        </mop>
        <speed xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
          <value-1000/>
        </speed>
        <negotiation xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-ethernet">
          <auto>false</auto>
        </negotiation>
      </GigabitEthernet>
      <GigabitEthernet>
      [...]<jupyter_text>Retrieve Interface Data (Native Model) With XPath QueryAs well as subtree filters, **IOS-XE** supports XPath-based filters.<jupyter_code>filter = '/native/interface/GigabitEthernet/name'

c = m.get_config(source='running', filter=('xpath', filter))
pretty_print(c)<jupyter_output><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <interface>
      <GigabitEthernet>
        <name>1</name>
      </GigabitEthernet>
      <GigabitEthernet>
        <name>2</name>
      </GigabitEthernet>
      <GigabitEthernet>
        <name>3</name>
      </GigabitEthernet>
      <GigabitEthernet>
        <name>4</name>
      </GigabitEthernet>
    </interface>
  </native>
</data><jupyter_text>Retrieve All BGP DataNow let's look at the BGP native model:<jupyter_code>filter = '''
<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
 <router>
   <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp"/>
 </router>
</native>
'''
c = m.get_config(source='running', filter=('subtree', filter))
pretty_print(c)<jupyter_output><empty_output><jupyter_text>Look At A Specific BGP NeighborAnd can we look at a specific neighbor only? Say the one with id (address) ```2.2.2.3```?<jupyter_code>filter = '''
<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <router>
    <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
      <id>100</id>
      <neighbor>
        <id>2.2.2.3</id>
      </neighbor>
        <address-family>
          <no-vrf>
            <ipv4>
              <af-name>unicast</af-name>
              <ipv4-unicast>
                <neighbor>
                  <id>2.2.2.3</id>
                </neighbor>
              </ipv4-unicast>
            </ipv4>
          </no-vrf>
        </address-family>
    </bgp>
  </router>
</native>
'''
c = m.get_config(source='running', filter=('subtree', filter))
pretty_print(c)<jupyter_output><empty_output><jupyter_text>Create New BGP NeighborOk, so, yes we can get a specific neighbor. Now, can we create a new neighbor? Let's create one with an id of `2.2.2.4`, with a remote-as of 666.<jupyter_code>from ncclient.operations import TimeoutExpiredError

edit_data = '''
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <router>
      <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
        <id>100</id>
        <neighbor>
          <id>2.2.2.4</id>
          <remote-as>666</remote-as>
        </neighbor>
        <address-family>
          <no-vrf>
            <ipv4>
              <af-name>unicast</af-name>
              <ipv4-unicast>
                <neighbor>
                  <id>2.2.2.4</id>
                  <activate/>
                </neighbor>
              </ipv4-unicast>
            </ipv4>
          </no-vrf>
        </address-family>
      </bgp>
    </router>
  </native>
</config>
'''

try:
    with m.locked(target='running'):
        edit_reply = m.edit_config(edit_data, target='running', format='xml')
except TimeoutExpiredError as e:
    print("Operation timeout!")
except Exception as e:
    print("severity={}, tag={}".format(e.severity, e.tag))
    print(e)<jupyter_output><empty_output><jupyter_text>Now let's pull back some of the data for that neighbor:<jupyter_code>filter = '''
<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
  <router>
    <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
      <id>100</id>
      <neighbor>
        <id>2.2.2.4</id>
      </neighbor>
    </bgp>
  </router>
</native>
'''
c = m.get_config(source='running', filter=('subtree', filter))
pretty_print(c)<jupyter_output><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <router>
      <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
        <id xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">100</id>
        <neighbor>
          <id xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">2.2.2.4</id>
          <remote-as>666</remote-as>
          <timers>
            <keepalive-interval>60</keepalive-interval>
            <holdtime>180</holdtime>
          </timers>
        </neighbor>
      </bgp>
    </router>
  </native>
</data><jupyter_text>Modify The BGP Neighbor DescriptionCan modify something in the neighbor we just created? Let's keep it simple and modify the description:<jupyter_code>from ncclient.operations import TimeoutExpiredError

edit_data = '''
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <router>
      <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
        <id>100</id>
        <neighbor>
          <id>2.2.2.4</id>
          <description nc:operation="merge">*** MODIFIED DESCRIPTION ***</description>
        </neighbor>
      </bgp>
    </router>
  </native>
</config>
'''

try:
    with m.locked(target='running'):
        edit_reply = m.edit_config(edit_data, target='running', format='xml')
except TimeoutExpiredError as e:
    print("Operation timeout!")
except Exception as e:
    print("severity={}, tag={}".format(e.severity, e.tag))
    print(e)<jupyter_output><empty_output><jupyter_text>Delete A BGP Neighbor<jupyter_code>from ncclient.operations import TimeoutExpiredError
from lxml.etree import XMLSyntaxError

edit_data = '''
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <router>
      <bgp xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-bgp">
        <id>100</id>
        <neighbor nc:operation="delete">
          <id>2.2.2.4</id>
        </neighbor>
        <address-family>
          <no-vrf>
            <ipv4>
              <af-name>unicast</af-name>
              <ipv4-unicast>
                <neighbor nc:operation="delete">
                  <id>2.2.2.4</id>
                </neighbor>
              </ipv4-unicast>
            </ipv4>
          </no-vrf>
        </address-family>
      </bgp>
    </router>
  </native>
</config>
'''

try:
    with m.locked(target='running'):
        edit_reply = m.edit_config(edit_data, target='running', format='xml')
except TimeoutExpiredError as e:
    print("Operation timeout!")
except XMLSyntaxError as e:
    print(e)
    print(e.args)
    print(dir(e))
except Exception as e:
    print("severity={}, tag={}".format(e.severity, e.tag))
    print(e)<jupyter_output>severity=error, tag=data-missing
{'type': 'application', 'tag': 'data-missing', 'severity': 'error', 'info': '<?xml version="1.0" encoding="UTF-8"?><error-info xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><bad-element>neighbor</bad-element>\n</error-info>\n', 'path': "\n    /nc:rpc/nc:edit-config/nc:config/ios:native/ios:router/ios-bgp:bgp[ios-bgp:id='100']/ios-bgp:neighbor[ios-bgp:id='2.2.2.4']\n  ", 'message': None}<jupyter_text>Other Stuff  Get interface operational data from native model:<jupyter_code>filter = '''
<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
  <interface/>
</interfaces>
'''
c = m.get(filter=('subtree', filter))
pretty_print(c)<jupyter_output><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
    <interface>
      <name>Control Plane</name>
      <interface-type>iana-iftype-other</interface-type>
      <admin-status>if-state-up</admin-status>
      <oper-status>if-oper-state-ready</oper-status>
      <last-change>2020-01-19T15:11:26.873+00:00</last-change>
      <if-index>0</if-index>
      <phys-address>00:00:00:00:00:00</phys-address>
      <speed>10240000000</speed>
      <statistics>
        <discontinuity-time>2020-01-19T15:09:37+00:00</discontinuity-time>
        <in-octets>0</in-octets>
        <in-unicast-pkts>0</in-unicast-pkts>
        <in-broadcast-pkts>0</in-broadcast-pkts>
        <in-multicast-pkts>0</in-multicast-pkts>
        <in-discards>0</in-discards>
        <in-errors>0</in-errors>
        <in-unknown-protos>0</in-unknown-protos>
        <out-octets>0</out-octets>
        <[...]<jupyter_text>Get all interface names<jupyter_code>filter = '''
<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
  <interface>
    <name/>
  </interface>
</interfaces>
'''
c = m.get(filter=('subtree', filter))
pretty_print(c)<jupyter_output><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
    <interface>
      <name>Control Plane</name>
    </interface>
    <interface>
      <name>GigabitEthernet1</name>
    </interface>
    <interface>
      <name>GigabitEthernet2</name>
    </interface>
    <interface>
      <name>GigabitEthernet3</name>
    </interface>
    <interface>
      <name>GigabitEthernet4</name>
    </interface>
    <interface>
      <name>Loopback100</name>
    </interface>
  </interfaces>
</data><jupyter_text>Get the statistics from a specific interface:<jupyter_code>filter = '''
<interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
  <interface>
    <name>GigabitEthernet1</name>
    <statistics/>
  </interface>
</interfaces>
'''
c = m.get(filter=('subtree', filter))
pretty_print(c)<jupyter_output><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-interfaces-oper">
    <interface>
      <name xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">GigabitEthernet1</name>
      <statistics>
        <discontinuity-time>2020-01-19T15:09:37+00:00</discontinuity-time>
        <in-octets>797761</in-octets>
        <in-unicast-pkts>7650</in-unicast-pkts>
        <in-broadcast-pkts>0</in-broadcast-pkts>
        <in-multicast-pkts>0</in-multicast-pkts>
        <in-discards>0</in-discards>
        <in-errors>0</in-errors>
        <in-unknown-protos>0</in-unknown-protos>
        <out-octets>6697678</out-octets>
        <out-unicast-pkts>6734</out-unicast-pkts>
        <out-broadcast-pkts>0</out-broadcast-pkts>
        <out-multicast-pkts>0</out-multicast-pkts>
        <out-discards>0</out-discards>
        <out-errors>0</out-errors>
        <rx-pps>0</rx-pps>
        <rx-kbps>0</rx-[...]<jupyter_text>Exercise Constraints  Create a VRF and put an interface into it<jupyter_code>from ncclient.operations import TimeoutExpiredError

edit_data = '''
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <interface>
      <GigabitEthernet>
        <name>4</name>
        <vrf>
          <forwarding>TEST</forwarding>
        </vrf>
        <ip>
          <address>
            <primary>
              <address>192.168.1.222</address>
              <mask>255.255.255.0</mask>
            </primary>
          </address>
        </ip>
      </GigabitEthernet>
    </interface>
    <vrf>
      <definition>
        <name>TEST</name>
        <address-family>
          <ipv4/>
        </address-family>
      </definition>
    </vrf>
  </native>
</config>
'''

try:
    with m.locked(target='running'):
        edit_reply = m.edit_config(edit_data, target='running', format='xml')
except TimeoutExpiredError as e:
    print("Operation timeout!")
except Exception as e:
    print("severity={}, tag={}".format(e.severity, e.tag))
    print(e)<jupyter_output><empty_output><jupyter_text>Try to delete the VRF<jupyter_code>from ncclient.operations import TimeoutExpiredError

edit_data = '''
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <vrf>
      <definition nc:operation="delete">
        <name>TEST</name>
      </definition>
    </vrf>
  </native>
</config>
'''

try:
    with m.locked(target='running'):
        edit_reply = m.edit_config(edit_data, target='running', format='xml')
except TimeoutExpiredError as e:
    print("Operation timeout!")
except Exception as e:
    print("severity={}, tag={}".format(e.severity, e.tag))
    print(e)<jupyter_output><empty_output><jupyter_text>Delete the VRF right<jupyter_code>from ncclient.operations import TimeoutExpiredError
import textwrap

# get all interfaces where VRF "TEST" is bound
xpath = "/native/interface/*/vrf[forwarding='TEST']"
c = m.get(filter=('xpath', xpath))

# set operation=delete on every VRF found
for e in c.data.xpath('//*[local-name()="vrf"]'):
    e.attrib['{urn:ietf:params:xml:ns:netconf:base:1.0}operation'] = "delete"

# find the node "native" and add it to a config node and then run an edit
config = etree.Element(
        "config",
        nsmap = {None: 'urn:ietf:params:xml:ns:netconf:base:1.0'})
config.append(c.data.xpath('//*[local-name()="native"]')[0])

# display what we will try to delete
print('What we will no try to delete:\n')
to_delete = etree.tostring(config, pretty_print=True).decode()
print(textwrap.indent(to_delete, '  ') )

# now delete the VRF from, the interface
try:
    with m.locked(target='running'):
        edit_reply = m.edit_config(config, target='running', format='xml')
except TimeoutExpiredError as e:
    print("Operation timeout!")
except Exception as e:
    print("severity={}, tag={}".format(e.severity, e.tag))
    print(e)<jupyter_output><empty_output><jupyter_text>Try put an interface into a non-existent VRF<jupyter_code>from ncclient.operations import TimeoutExpiredError

edit_data = '''
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <interface>
      <GigabitEthernet>
        <name>3</name>
        <vrf>
          <forwarding>DOES_NOT_EXIST</forwarding>
        </vrf>
        <ip>
          <address>
            <primary>
              <address>192.168.2.222</address>
              <mask>255.255.255.0</mask>
            </primary>
          </address>
        </ip>
      </GigabitEthernet>
    </interface>
  </native>
</config>
'''

try:
    with m.locked(target='running'):
        edit_reply = m.edit_config(edit_data, target='running', format='xml')
except TimeoutExpiredError as e:
    print("Operation timeout!")
except Exception as e:
    print("severity={}, tag={}".format(e.severity, e.tag))
    print(e)<jupyter_output><empty_output><jupyter_text>Alternate XML Creation<jupyter_code>from lxml import etree

def create_interface_filter(intf_name):
    interfaces = etree.Element(
        "interfaces",
        nsmap = {None: 'http://openconfig.net/yang/interfaces'})
    interface = etree.SubElement(interfaces, "interface")
    etree.SubElement(interface, 'name').text = intf_name
    state = etree.SubElement(interface, 'state')
    etree.SubElement(state, 'counters')
    return interfaces

print(etree.tostring(create_interface_filter('MgmtEth0/RP0/CPU0/0'), pretty_print=True))
print(etree.tostring(create_interface_filter('GigabitEthernet1'), pretty_print=True))<jupyter_output><empty_output><jupyter_text>Enable Debugging<jupyter_code>import logging

handler = logging.StreamHandler()
for l in ['ncclient.transport.ssh', 'ncclient.transport.session', 'ncclient.operations.rpc']:
    logger = logging.getLogger(l)
    logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16369536641472232, 'fraction_numerical': 0.023126848504765034, 'mean_word_length': 3.5778488153441144, 'pattern_counts': {'":': 0, '<': 510, '<?xml version=': 1, '>': 508, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 106}, 'pii_count': 17, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '26', 'dir': 'jupyter-structured-clean-dedup', 'id': '617959', 'license': 'Apache-2.0', 'n_tokens_mistral': 9396, 'n_tokens_neox': 8972, 'n_words': 1371, 'path': 'notebooks/CLEU-2020.ipynb', 'repo_name': 'tbearma1/ncc', 'size': '24342'}