python網絡自動化ncclient模塊,netconf協議檢索與下發交換機配置


以juniper和華為設備為例

交換機必要配置,配置簡單,使用ssh模式傳輸

#juniper
set system services netconf ssh
#華為

local-user netconf-dark password irreversible-cipher $1c$16[R/:A_aG$sG-KWmUb!SCz=R9y[P%KE&9.'P"+:XJ=-`<S76p.$
local-user netconf-dark privilege level 15
local-user netconf-dark service-type api

netconf
source ip 10.0.3.105

netconf使用XML格式來請求和接收數據,使用簡單舉例

使用ssh連接交換機

C:\Users\86185>ssh  10.0.3.101 -s netconf
Password:
<!-- No zombies were killed during the creation of this user interface -->
<!-- user dark, class j-super-user -->
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capabilities>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:confirmed-commit:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:validate:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:url:1.0?scheme=http,ftp,file</capability>
    <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:candidate:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:validate:1.0</capability>
    <capability>urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file</capability>
    <capability>http://xml.juniper.net/netconf/junos/1.0</capability>
    <capability>http://xml.juniper.net/dmi/system/1.0</capability>
  </capabilities>
  <session-id>65770</session-id>
</hello>
]]>]]>

juniper請求端口信息

<rpc>
    <get-interface-information>
        <interface-name>xe-0/0/1</interface-name>
        <detail/>
    </get-interface-information>
</rpc>

juniper提交配置

<rpc>
<commit/>
</rpc>

華為請求trunk接口信息

<?xml version="1.0" encoding="UTF-8"?>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1024">
  <get>
    <filter type="subtree">
      <ifmtrunk xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
        <TrunkIfs>
          <TrunkIf>
            <ifName></ifName>
            <minUpNum></minUpNum>
            <trunkType></trunkType>
          </TrunkIf>
        </TrunkIfs>
      </ifmtrunk>
    </filter>
  </get>
</rpc>

以上是netconf的簡單原生操作,如果我們要在python環境中使用netconf,首先需要下載讀取YANG文件,封裝get get-config commit edit_config lock unlock等功能,根據不同廠商選擇不同的YANG API,其次還需要創建sock連接,通過ssh交互netconf報文,設備廠商繁多,各家功能對應的TAG名稱也不一致,自己一步一步寫起來太過復雜,好在python中有較為成熟的庫可供我們使用

 


ncclient

ncclient是一個用於NETCONF客戶端的Python庫,可以在python環境中使用netconf協議檢索下發交換機配置

host = '10.0.3.105'
username = 'username'
passwd = 'password'
#connect()返回一個連接對象
netconf_connection = manager.connect(host=host,
                                     username=username,
                                     password=passwd,
                                     port=830,
                                     hostkey_verify=False
                                     )

#獲取交換機端口簡要信息XML語句
interface_index = """
        <device-state xmlns="urn:huawei:params:xml:ns:yang:huawei-device">
        <optical-module-infos>
             <interface-list>
             </interface-list>
             </optical-module-infos>
          </device-state>
"""

rpc_conf = netconf_connection.get(filter =('subtree',interface_info))

print(rpc)

得到如下信息

<?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><device-state xmlns="urn:huawei:params:xml:ns:yang:huawei-device"><optical-module-infos><interface-list><interface-name>XGigabitEthernet0/0/1</interface-name><physical-index>1</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/2</interface-name><physical-index>2</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/3</interface-name><physical-index>3</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/4</interface-name><physical-index>4</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/5</interface-name><physical-index>5</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/6</interface-name><physical-index>6</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/7</interface-name><physical-index>7</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/8</interface-name><physical-index>8</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/9</interface-name><physical-index>9</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/10</interface-name><physical-index>10</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/11</interface-name><physical-index>11</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/12</interface-name><physical-index>12</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/13</interface-name><physical-index>13</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/14</interface-name><physical-index>14</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/15</interface-name><physical-index>15</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/16</interface-name><physical-index>16</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/17</interface-name><physical-index>17</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/18</interface-name><physical-index>18</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/19</interface-name><physical-index>19</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/20</interface-name><physical-index>20</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/21</interface-name><physical-index>21</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/22</interface-name><physical-index>22</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/23</interface-name><physical-index>23</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/24</interface-name><physical-index>24</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/25</interface-name><physical-index>25</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/26</interface-name><physical-index>26</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/27</interface-name><physical-index>27</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/28</interface-name><physical-index>28</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/29</interface-name><physical-index>29</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/30</interface-name><physical-index>30</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/31</interface-name><physical-index>31</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/32</interface-name><physical-index>32</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/33</interface-name><physical-index>33</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/34</interface-name><physical-index>34</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/35</interface-name><physical-index>35</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/36</interface-name><physical-index>36</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/37</interface-name><physical-index>37</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/38</interface-name><physical-index>38</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/39</interface-name><physical-index>39</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/40</interface-name><physical-index>40</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/41</interface-name><physical-index>41</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/42</interface-name><physical-index>42</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/43</interface-name><physical-index>43</physical-index><present>false</present></interface-list><interface-list><interface-name>XGigabitEthernet0/0/44</interface-name><physical-index>44</physical-index><present>false</present></interface-list><interface-list><interface-name>100GE0/0/1</interface-name><physical-index>1</physical-index><present>false</present></interface-list><interface-list><interface-name>100GE0/0/2</interface-name><physical-index>2</physical-index><present>false</present></interface-list><interface-list><interface-name>40GE0/0/3</interface-name><physical-index>3</physical-index><present>false</present></interface-list><interface-list><interface-name>40GE0/0/4</interface-name><physical-index>4</physical-index><present>false</present></interface-list><interface-list><interface-name>40GE0/0/5</interface-name><physical-index>5</physical-index><present>false</present></interface-list><interface-list><interface-name>40GE0/0/6</interface-name><physical-index>6</physical-index><present>false</present></interface-list></optical-module-infos></device-state></data>
View Code

請問這一堆亂糟糟的是什么東西,也沒個換行符-_-!

別急,我們需要封裝一些功能進去

 1 #首先自己寫一個類
 2 class Netconf:
 3     #封裝一些connect必要的參數
 4     def __init__(self,*args,**kwargs):
 5         self.host = kwargs['host']
 6         self.port = kwargs.get('port',830)
 7         self.username = kwargs['username']
 8         self.passwd = kwargs['passwd']
 9         self.hostkey_verify=kwargs.get('hostkey_verify',False) 
10     #connect方法
11     def conn(self):
12         try:
13             netconf_conn =  manager.connect(host=self.host,port=self.port,username=self.username,password=self.passwd,hostkey_verify=self.hostkey_verify)
14             return netconf_conn
15         except Exception as a:
16             print(a)
17             print("""
18             ---------------------------------------------------------------------------------------
19             sample: Netconf(host='10.0.3.105',username='netconf-dark',passwd='1234567',port=830)
20             """
21             )
22     #get_config方法,獲取的交換機的所有配置
23     def get_conf(self):
24         netconf_conn = self.conn()
25         return netconf_conn.get_config(source='running').data_xml
26     #寫個方法處理下得到的數據,以xml樹形格式進行返回
27     def get_xml(self,command=None):
28         netconf_conn = self.conn()
29         rpc_replay = netconf_conn.get(filter=('subtree',command)).data_xml
30         rpc_xml = xml.dom.minidom.parseString(rpc_replay).toprettyxml()
31         return rpc_replay
32     #以字典形式進行返回,方便做數據處理
33     def get_dic(self,command=None):
34         netconf_conn = self.conn()
35         rpc_replay = netconf_conn.get(filter=('subtree',command)).data_xml
36         rpc_dict = xmltodict.parse(rpc_replay)
37         return rpc_dict
38     #以json方式進行返回
39     def get_json(self,command=None):
40         rpc_replay = self.get_dic(command)
41         rpc_json = json.dumps(rpc_replay, indent=1)
42         return rpc_json
43     def server_capabilities(self):
44         netconf_conn = self.conn()
45         return netconf_conn.server_capabilities

我們來用下好不好使

interface_info = """
<interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
    <name></name>
    <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
        <address></address>
    </ipv4> 
</interface>
</interfaces-state>
"""
conn = Netconf(host='10.0.3.105',username='netconf',passwd='netconf123456')
rpc_json = conn.get_json(interface_index)
rpc_xml = conn.get_xml(interface_index)
with open('/home/dark/interface_info.json') as a:
    a.write(rpc_json)
with open('/home/dark/interface_info.xml') as a:
    a.write(rpc_xml)

運行以上代碼

#json格式,輸出太長,截取一小段
{
 "data": {
  "@xmlns": "urn:ietf:params:xml:ns:netconf:base:1.0",
  "@xmlns:nc": "urn:ietf:params:xml:ns:netconf:base:1.0",
  "interfaces-state": {
   "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-interfaces",
   "interface": [
    {
     "name": "NULL0"
    },
    {
     "name": "MEth0/0/1"
    },
    {
     "name": "Vlanif1"
    },
    {
     "name": "XGigabitEthernet0/0/1"
    },
    {
     "name": "XGigabitEthernet0/0/2"
    },
    {
     "name": "XGigabitEthernet0/0/3"
    },
    {
     "name": "XGigabitEthernet0/0/4"
    },
    {
     "name": "40GE0/0/3"
    },
    {
     "name": "40GE0/0/4"
    },
    {
     "name": "40GE0/0/5"
    },
    {
     "name": "40GE0/0/6"
    },
    {
     "name": "LoopBack0",
     "ipv4": {
      "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-ip",
      "address": {
       "ip": "192.168.35.60",
       "netmask": "255.255.255.255",
       "origin": "static"
      }
     }
    },
    {
     "name": "Vlanif48",
     "ipv4": {
      "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-ip",
      "address": {
       "ip": "10.40.0.70",
       "netmask": "255.255.255.252",
       "origin": "static"
      }
     }
    },
    {
     "name": "LoopBack1",
     "ipv4": {
      "@xmlns": "urn:ietf:params:xml:ns:yang:ietf-ip",
      "address": {
       "ip": "192.168.39.17",
       "netmask": "255.255.255.252",
       "origin": "static"
      }
     }
    },
    {
     "name": "MEth0/0/2"
    }
   ]
  }
 }
}
json格式
#XML格式,輸出太長,截取一小段
<?xml version="1.0" ?>
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
    <interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
        <interface>
            <name>NULL0</name>
        </interface>
        <interface>
            <name>MEth0/0/1</name>
        </interface>
        <interface>
            <name>Vlanif1</name>
        </interface>
        <interface>
            <name>XGigabitEthernet0/0/1</name>
        </interface>
        <interface>
            <name>XGigabitEthernet0/0/2</name>
        </interface>
        <interface>
            <name>XGigabitEthernet0/0/3</name>
        </interface>
        <interface>
            <name>40GE0/0/3</name>
        </interface>
        <interface>
            <name>40GE0/0/4</name>
        </interface>
        <interface>
            <name>40GE0/0/5</name>
        </interface>
        <interface>
            <name>40GE0/0/6</name>
        </interface>
        <interface>
            <name>LoopBack0</name>
            <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
                <address>
                    <ip>192.168.35.60</ip>
                    <netmask>255.255.255.255</netmask>
                    <origin>static</origin>
                </address>
            </ipv4>
        </interface>
        <interface>
            <name>Nve1</name>
        </interface>
        <interface>
            <name>Vlanif48</name>
            <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
                <address>
                    <ip>10.40.0.70</ip>
                    <netmask>255.255.255.252</netmask>
                    <origin>static</origin>
                </address>
            </ipv4>
        </interface>
        <interface>
            <name>LoopBack1</name>
            <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
                <address>
                    <ip>192.168.39.17</ip>
                    <netmask>255.255.255.252</netmask>
                    <origin>static</origin>
                </address>
            </ipv4>
        </interface>
        <interface>
            <name>MEth0/0/2</name>
        </interface>
    </interfaces-state>
</data>
XML格式

 代碼中的interfac_info的XML字符串來自哪里?這就需要用到YANG API,有公共的YANG,各家廠商也有自己的YANG

例如華為CE系列的https://support.huawei.com/hedex/hdx.do?docid=EDOC1000179511&lang=zh&id=library_change_preview&from=HedExLite

也可以通過get請求格式化成XML文檔樹,如下

 juniper還可以通過命令行輸出XML格式,華為沒找類似功能,可能是我手里的交換機太垃圾

 如果是通過YANG API文件檢索的字符串,我們用ncclient執行操作時只需要content部分,如下黑色框區域

 如果是get到的XML文檔樹,需要哪個模塊就點開哪個模塊復制就行,例如我們需要獲取每個端口的ipaddress,如下

先找到interfaces-state這一層,展開

 我們可以獲取關於接口的N多信息,如果我們只需要其中的一部分可以進行如下操作

interface_info = """
<interfaces-state xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
    <name></name>
    <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
        <address></address>
    </ipv4> 
</interface>
</interfaces-state>
"""
#根層必須有,子層的父層也必須有,到子層后需要哪些標簽就寫對應的標簽
rpc_xml = conn.get_xml(interface_info)
print(rpc_xml)

輸出如下,截取部分

同樣的,juniper通過GET到XML結構樹,這里不得不感嘆下juniper的便捷,靈活性,從以下輸出可以看到juniper的XML樹形結構與配置命令的層次結構極其相似

 來get一下接口信息,這次輸出json格式

rpc_json = conn.get_json('<configuration><interfaces></interfaces></configuration>')
print(rpc_json)

運行以上代碼,截取一小部分

 以上是ncclient的GET操作,ncclient的manager模塊還有許多其他方法,如下

接着說edit_config和commit,discard_changss,這些方法用於對交換機配置的變更,我們需要封裝進我們自己的類,改變如下

 1 class Netconf:
 2     #封裝一些connect必要的參數
 3     def __init__(self,*args,**kwargs):
 4         self.host = kwargs['host']
 5         self.port = kwargs.get('port',830)
 6         self.username = kwargs['username']
 7         self.passwd = kwargs['passwd']
 8         self.hostkey_verify=kwargs.get('hostkey_verify',False) 
 9         self.device_params=kwargs.get('device_params',None)
10     #connect方法
11     def conn(self):
12         try:
13             netconf_conn =  manager.connect(host=self.host,port=self.port,username=self.username,\
14                 password=self.passwd,hostkey_verify=self.hostkey_verify,device_params=self.device_params)
15             return netconf_conn
16         except Exception as a:
17             print(a)
18             print("""
19             ---------------------------------------------------------------------------------------
20             sample: Netconf(host='10.0.3.105',username='netconf-dark',passwd='1234567',port=830)
21             """
22             )
23     #get_config方法,獲取的交換機的所有配置
24     def get_conf(self):
25         netconf_conn = self.conn()
26         return netconf_conn.get_config(source='running').data_xml
27     #寫個方法處理下得到的數據,以xml樹形格式進行返回
28     def get_xml(self,command=None):
29         netconf_conn = self.conn()
30         rpc_replay = netconf_conn.get(filter=('subtree',command)).data_xml
31         rpc_xml = xml.dom.minidom.parseString(rpc_replay).toprettyxml()
32         
33         return rpc_xml.strip()
34     #以字典形式進行返回,方便做數據處理
35     def get_dic(self,command=None):
36         netconf_conn = self.conn()
37         rpc_replay = netconf_conn.get(filter=('subtree',command)).data_xml
38         rpc_dict = xmltodict.parse(rpc_replay)
39         return rpc_dict
40     #以json方式進行返回
41     def get_json(self,command=None):
42         rpc_replay = self.get_dic(command)
43         rpc_json = json.dumps(rpc_replay, indent=1)
44         return rpc_json
45     #server端所支持的能力,返回迭代器
46     def server_capabilities(self):
47         netconf_conn = self.conn()
48         return netconf_conn.server_capabilities
49     #edit_config方法,target可使用candidate或running
50     def edit(self,command=None,target='candidate'):
51         netconf_conn = self.conn()
52         reply = netconf_conn.edit_config(target=target,config=command)
53         return reply
54     #清除未提交配置
55     def rollback(self):
56         netconf_conn = self.conn()
57         # netconf_conn.rpc('<discard-changes/>')
58         return netconf_conn.discard_changes()
59 
60     #提交配置,confirmed代表是否進行回滾,timout表示多久回滾
61     def commit(self,confirmed=False,timeout=None):
62         netconf_conn = self.conn()
63         return netconf_conn.commit(confirmed=confirmed,timeout=timeout)

 

edit_config方法有一個必要的參數,config,XML格式,target參數需要注意,值可為candidate或running,對於juniper必須使用candidate,因為juniper配置完設備后需要commit提交配置

 

首先我們使用 server_capabilities方法看下設備是否支持edit_config

jun_conn = Netconf(host='10.0.3.101',username='username',passwd='passwd',port=1211,device_params={'name':'junos'})
hw_conn = Netconf(host='10.0.3.105',username='netconf',passwd='passwd')

for cap in hw_conn.server_capabilities():
    print(cap)

for cap in jun_conn.server_capabilities():
    print(cap)

輸出如下,juniper對網絡可編程支持性較好,操作舒服,以下案例均使用juniper設備

#HW

rn: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:candidate:1.0
urn:ietf:params:netconf:capability:startup:1.0
urn:ietf:params:netconf:capability:rollback-on-error:1.0
urn:ietf:params:netconf:capability:with-defaults:1.0
urn:ietf:params:netconf:capability:notification:1.0
urn:ietf:params:xml:ns:yang:1?revision=2017-02-20&module=yang
urn:ietf:params:xml:ns:yang:ietf-inet-types?revision=2013-07-15&module=ietf-inet-types
urn:ietf:params:xml:ns:yang:ietf-yang-types?revision=2013-07-15&module=ietf-yang-types
urn:ietf:params:xml:ns:yang:ietf-yang-library?revision=2018-01-17&module=ietf-yang-library
urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08&module=ietf-interfaces&feature=arbitrary-names,pre-provisioning,if-mib
#輸出太多,截取一部分,如上支持的module,測試交換機是s6720,xml固定格式是
<huawei-vlan:vlans xmlns:huawei-vlan="urn:huawei:params:xml:ns:yang:huawei-vlan" >
#最后的yang:后面跟交換機支持的模塊,操作對應的模塊
#<huawei-vlan:vlan xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="delete"> 操作類型前需要跟前面一長串
#juniper
urn:ietf:params:netconf:base:1.0
urn:ietf:params:netconf:capability:candidate:1.0
urn:ietf:params:netconf:capability:confirmed-commit:1.0
urn:ietf:params:netconf:capability:validate:1.0
urn:ietf:params:netconf:capability:url:1.0?scheme=http,ftp,file
urn:ietf:params:xml:ns:netconf:base:1.0
urn:ietf:params:xml:ns:netconf:capability:candidate:1.0
urn:ietf:params:xml:ns:netconf:capability:confirmed-commit:1.0
urn:ietf:params:xml:ns:netconf:capability:validate:1.0
urn:ietf:params:xml:ns:netconf:capability:url:1.0?protocol=http,ftp,file
http://xml.juniper.net/netconf/junos/1.0
http://xml.juniper.net/dmi/system/1.0

來使用下我們新增的方法,通用YANG API edit_config方法使用的tag是<config>,內層標簽則需要查找設備廠商所提供的API

jun_conn = Netconf(host='10.0.3.101',username='usernam',passwd='password',port=1211,device_params={'name':'junos'})

snmp = '''
<config>
    <configuration>
        <snmp>
        <community>
        <name>dark123456</name>
        <authorization>read-only</authorization>
        </community>
        </snmp>
    </configuration>
</config>
'''
jun_conn.edit(snmp)

運行以上代碼后在設備上可以看到配置已經下發,但未提交,需要注意的是對於華為設備如果candidate數據庫中有未提交配置時不可操作running數據庫

dark@Test-Route# show | compare 
[edit snmp]
    community 000123a { ... }
+   community dark123456 {
+       authorization read-only;
+   }

[edit]

dark@Test-Route> show configuration snmp | display set
set snmp community test authorization read-only

 

運行以下代碼進行配置回滾

jun_conn.rollback()

執行后在設備上查看未提交配置為空

讓我們回到下發配置未提交時,執行以下方法,commit並在1分鍾后回滾配置

jun_conn.edit(snmp)
jun_conn.commit(confirmed=True,timeout=60)

 可以看到配置將在1分鍾內回滾

執行jun_conn.commit(),查看設備配置,配置已經下發並提交

 然后我們進行配置刪除

執行以下代碼

del_snmp = '''
<config>
<configuration>
        <snmp>
        <community operation="delete">
        <name>dark123456</name>
        <authorization>read-only</authorization>
        </community>
        </snmp>
</configuration>
</config>'''

jun_conn.edit(del_snmp)
jun_conn.commit()

 配置已刪除

再試下華為設備,添加vlan 671

 執行以下代碼

vlan = '''
        <config>
            <huawei-vlan:vlans xmlns:huawei-vlan="urn:huawei:params:xml:ns:yang:huawei-vlan" >
                <huawei-vlan:vlan>
                    <huawei-vlan:id >671</huawei-vlan:id>
                </huawei-vlan:vlan>
            </huawei-vlan:vlans>
        </config>
'''
hw_conn.edit(command=vlan,target='running')

 刪除vlan執行以下代碼

del_vlan = '''
        <config>
            <huawei-vlan:vlans xmlns:huawei-vlan="urn:huawei:params:xml:ns:yang:huawei-vlan" >
                <huawei-vlan:vlan xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="delete">
                    <huawei-vlan:id >671</huawei-vlan:id>
                </huawei-vlan:vlan>
            </huawei-vlan:vlans>
        </config>
'''
hw_conn.edit(del_vlan)

 

 

至此ncclient基本增刪改查方法與格式化輸出封裝完畢

 

出門溜娃,下周繼續.................


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM