YANG模型定义了一个层次化的数据结构,可用于基于网络配置管理协议如NETCONF或RESTCONF的运维。这些运维操作包括配置、状态、rpc和通知。与SNMP的模型MIB相比,YANG更加层次化,可以区分配置和状态,更具扩展性。
NETCONF跟RESTCONF的区别是netconf是基于SSH的,而resetconf是基于http的。对于目前大多数设备来说,支持netconf的会比支持restconf更多。
YIN(YANG Independent Notation)是XML格式的YANG。
NETCONF使得对网络设备读取状态和下发配置更加方便。
华为案例
初始化交换机
sysname CE-Switch-01
#
aaa
local-user netconf password cipher Huawei@123
local-user netconf service-type ssh
local-user netconf level 3
#
ssh user netconf
ssh user netconf authentication-type password
ssh user netconf service-type snetconf
#
netconf
protocol inbound ssh port 830
from ncclient import manager
import xmltodict
class Huawei_netconf():
def __init__(self, ipaddr, port, username, password):
self.host = ipaddr
self.port = port
self.username = username
self.password = password
self.sysinfo_filter = '''
<system xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
<systemInfo>
<sysName></sysName>
<sysContact></sysContact>
<sysLocation></sysLocation>
</systemInfo>
</system>
'''
self.vrpinfo_filter = '''
<sum xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
<softwareversions>
<softwareversion>
</softwareversion>
</softwareversions>
</sum>
'''
def huawei_connect(self):
return manager.connect(host=self.host,
port=self.port,
username=self.username,
password=self.password,
hostkey_verify = False,
device_params={'name': "huawei"},
allow_agent = False,
look_for_keys = False)
def ncc_get(self):
with self.huawei_connect() as m:
sysinfo = m.get(("subtree", self.sysinfo_filter))
vrpinfo = m.get(("subtree", self.vrpinfo_filter))
return sysinfo, vrpinfo
if __name__ == '__main__':
hw_netconf = Huawei_netconf('192.168.134.202', '830', 'netconf', 'Huawei@123')
sysinfo_res, vrpinfo_res = hw_netconf.ncc_get()
sysinfo_xml_res = sysinfo_res.data_xml
vrpinfo_xml_res = vrpinfo_res.data_xml
#使用xmltodict这个工具将xml格式的数据转换为字典
sysinfo_dict_res = xmltodict.parse(sysinfo_xml_res)
vrpinfo_dict_res = xmltodict.parse(vrpinfo_xml_res)
sysname = sysinfo_dict_res['data']['system']['systemInfo']['sysName']
vrp_version = vrpinfo_dict_res['data']['sum']['softwareversions']['softwareversion']['vrpversion']
print(f'设备名为: {sysname}')
print(f'VRP版本为: {vrp_version}')
Reference: https://zhuanlan.zhihu.com/p/390490650
A Csico Example
username admin privilege 15 secret admin
!
interface GigabitEthernet1
ip address 192.168.145.51 255.255.255.0
no shutdown
!
netconf-yang
- Discovering device capabilities
from ncclient import manager
m = manager.connect(host='192.168.145.51', port=830, username='admin',
password='admin', device_params={'name': 'csr'})
print m.server_capabilities
- Obtaining YANG models
schema = m.get_schema('ietf-ip')
print schema
import xml.etree.ElementTree as ET
root = ET.fromstring(schema.xml)
yang_text = list(root)[0].text
write_file('ietf-ip.yang', yang_text)
$ pyang -f tree ietf-ip.yang | head -
module: ietf-ip
augment /if:interfaces/if:interface:
+--rw ipv4!
| +--rw enabled? boolean
| +--rw forwarding? boolean
| +--rw mtu? uint16
| +--rw address* [ip]
| | +--rw ip inet:ipv4-address-no-zone
| | +--rw (subnet)
| | +--:(prefix-length)
module ietf-ip {
namespace "urn:ietf:params:xml:ns:yang:ietf-ip";
prefix ip;
import ietf-interfaces {
prefix if;
}
import ietf-inet-types {
prefix inet;
}
import ietf-yang-types {
prefix yang;
}
- Instantiating YANG models
pyang --plugindir $PYBINDPLUGIN -f pybind -o ietf_ip_binding.py ietf-ip.yang ietf-interfaces.yang ietf-inet-types.yang ietf-inet-types.yang
from ietf_ip_binding import ietf_interfaces
model = ietf_interfaces()
model.get()
{'interfaces': {'interface': {}}, 'interfaces-state': {'interface': {}}}
new_interface = model.interfaces.interface.add('GigabitEthernet2')
new_interface.get()
{'description': u'',
'enabled': True,
'ipv4': {'address': {},
'enabled': True,
'forwarding': False,
'mtu': 0,
'neighbor': {}},
'ipv6': {'address': {},
'autoconf': {'create-global-addresses': True,
'create-temporary-addresses': False,
'temporary-preferred-lifetime': 86400L,
'temporary-valid-lifetime': 604800L},
'dup-addr-detect-transmits': 1L,
'enabled': True,
'forwarding': False,
'mtu': 0L,
'neighbor': {}},
'link-up-down-trap-enable': u'',
'name': u'GigabitEthernet2',
'type': u''}
new_interface.description = 'NETCONF-CONFIGURED PORT'
new_interface.get()['description']
ipv4_addr = new_interface.ipv4.address.add('12.12.12.2')
ipv4_addr.get()
{'ip': u'12.12.12.2', 'netmask': u'', 'prefix-length': 0}
ipv4_addr.netmask = '255.255.255.0'
import pyangbind.lib.pybindJSON as pybindJSON
json_data = pybindJSON.dumps(model, mode='ietf')
write_file('new_interface.json',json_data)
print json_data
- Applying configuration changes
pyang -f jtox -o interface.jtox ietf-ip.yang ietf-interfaces.yang ietf-inet-types.yang ietf-yang-types.yang
json2xml -t config -o interface.xml interface.jtox interface.json
xml = read_file('interface.xml')
reply = m.edit_config(target='running', config=xml)
print("Success? {}".format(reply.ok))
m.close_session()
Router#sh run int gi 2
Building configuration...
Current configuration : 126 bytes
!
interface GigabitEthernet2
description NETCONF-CONFIGURED PORT
ip address 12.12.12.2 255.255.255.0
negotiation auto
end