#何がやりたい?
これまで、IOS-XE を対象としてNETCONFを使って設定できることを確認してきましたが、今回は、IOS-XR に対してNETCONFでルータを設定します。
##IOS-XR上でNETCONFを有効にする設定
conf t
ssh server v2
ssh server netconf port 830
ssh timeout 120
netconf-yang agent ssh
commit
end
crypto key generate rsa
conf t
control-plane
management-plane
inband
interface GigabitEthernet0/0/0/0
allow all
commit
end
今回の構成では、192.168.99.1がルータのアドレス、ユーザー名/パスワードがcisco/ciscoとなります。
##running-configを取得
まずは、現状のルータ(IOS-XR)からコンフィグを取得することから確認します。
NETCONF経由で設定したいコンフィグについては、まず最初に、ルータ上でコマンドラインから従来通り設定して、ここで取得したrunning-configの結果を参照して、以降で紹介しているように、スクリプトの中に引用するという流れが便利かなと思います。
#!/usr/bin/python
from ncclient import manager
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'iosxr'})
#response = m.get_config(source='running', filter=payload)
print '###########################################################################'
print '### XML'
print '###########################################################################'
response = m.get_config(source='running').data_xml
print response
下記は、取得した結果をJSONで表示したいだけです。特に深い理由はありません。
#!/usr/bin/python
from ncclient import manager
from xml.dom import minidom
import lxml.etree as ET
import xmltodict
import json
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'iosxr'})
#response = m.get_config(source='running', filter=payload)
print '###########################################################################'
print '### XML'
print '###########################################################################'
response = m.get_config(source='running').data_xml
print response
print '###########################################################################'
print '### XML Formatstring'
print '###########################################################################'
data = ET.fromstring(response)
print(ET.tostring(data, pretty_print=True))
print '###########################################################################'
print '### Convert to Dictionary'
print '###########################################################################'
data_dict = xmltodict.parse(response)
print(data_dict)
print '###########################################################################'
print '### Convert to JSON'
print '###########################################################################'
data_jason = json.dumps(data_dict, indent=4)
print(data_jason)
##hostnameを変更する
###XMLを直書きした場合
<config></config>
に挟まれた設定内容(hostnameのコンフィグ部分)は、先のrunning-configを取得した結果からコピー&ペーストで引用しています。
#!/usr/bin/env python
from ncclient import manager
from lxml import etree
config = """
<config>
<host-names xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg">
<host-name>CE01</host-name>
</host-names>
</config>
"""
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'default'}, look_for_keys=False, allow_agent=False)
print '======================================================================'
print '===== response ====='
print '======================================================================'
response = m.edit_config(config=config, default_operation="merge", target="candidate").xml
print response
response = m.commit()
print response
###ElementTreeモジュールを利用した場合
#!/usr/bin/env python
from ncclient import manager
from lxml import etree
from xml.dom import minidom
import xmltodict
import json
import datetime
# build xml
config_e = etree.Element("config")
hostname = etree.SubElement(config_e, "host-names", nsmap = {None: 'http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg'})
etree.SubElement(hostname, "host-name").text = 'CE01'
print '###########################################################################'
print '### XML'
print '###########################################################################'
print etree.tostring(config_e)
print '###########################################################################'
print '### XML Formatstring'
print '###########################################################################'
print etree.tostring(config_e, pretty_print=True)
print '###########################################################################'
print '### Convert to Dictionary'
print '###########################################################################'
data_dict = xmltodict.parse(etree.tostring(config_e))
print data_dict
print '###########################################################################'
print '### Convert to JSON'
print '###########################################################################'
data_jason = json.dumps(data_dict, indent=4)
print data_jason
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'default'}, look_for_keys=False, allow_agent=False)
print '======================================================================'
print '===== response ====='
print '======================================================================'
response = m.edit_config(config=config_e, default_operation="merge", target="candidate")
print response
response = m.commit()
print response
参考までに、下記が実行結果になります。XML Formatstring
の出力部分がXMLを直書き
した場合と同じ内容であることが確認できます。
$ python edit_hostname_etree.py
###########################################################################
### XML
###########################################################################
<config><host-names xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg"><host-name>CE01</host-name></host-names></config>
###########################################################################
### XML Formatstring
###########################################################################
<config>
<host-names xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg">
<host-name>CE01</host-name>
</host-names>
</config>
###########################################################################
### Convert to Dictionary
###########################################################################
OrderedDict([(u'config', OrderedDict([(u'host-names', OrderedDict([(u'@xmlns', u'http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg'), (u'host-name', u'CE01')]))]))])
###########################################################################
### Convert to JSON
###########################################################################
{
"config": {
"host-names": {
"@xmlns": "http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg",
"host-name": "CE01"
}
}
}
======================================================================
===== response =====
======================================================================
<?xml version="1.0"?>
<rpc-reply message-id="urn:uuid:3b59ff85-d686-4aa0-b0d9-8d7a952c09df" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<ok/>
</rpc-reply>
<?xml version="1.0"?>
<rpc-reply message-id="urn:uuid:bc03f285-9b91-41b1-9bb2-1c86e6a31cd0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<ok/>
</rpc-reply>
##interfaceのdescriptionを変更する
###XMLを直書きした場合
#!/usr/bin/env python
from ncclient import manager
from lxml import etree
config = """
<config>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
<interface-configuration>
<active>act</active>
<interface-name>GigabitEthernet0/0/0/0</interface-name>
<description>NETCONF configured - 2019-03-12 00:00:00</description>
</interface-configuration>
</interface-configurations>
</config>
"""
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'default'}, look_for_keys=False, allow_agent=False)
print '======================================================================'
print '===== response ====='
print '======================================================================'
response = m.edit_config(config=config, default_operation="merge", target="candidate").xml
print response
response = m.commit()
print response
###ElementTreeモジュールを利用した場合
#!/usr/bin/env python
from ncclient import manager
from lxml import etree
import datetime
from xml.dom import minidom
import xmltodict
import json
current_time = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')
# build xml
config_e = etree.Element("config")
interface01 = etree.SubElement(config_e, "interface-configurations", nsmap = {None: 'http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg'})
interface01_cfg = etree.SubElement(interface01, "interface-configuration")
etree.SubElement(interface01_cfg, "active").text = 'act'
etree.SubElement(interface01_cfg, "interface-name").text = 'GigabitEthernet0/0/0/10'
etree.SubElement(interface01_cfg, "description").text = 'NETCONF configured - ' + current_time
interface02 = etree.SubElement(config_e, "interface-configurations", nsmap = {None: 'http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg'})
interface02_cfg = etree.SubElement(interface01, "interface-configuration")
etree.SubElement(interface02_cfg, "active").text = 'act'
etree.SubElement(interface02_cfg, "interface-name").text = 'GigabitEthernet0/0/0/11'
etree.SubElement(interface02_cfg, "description").text = 'NETCONF configured - ' + current_time
print '###########################################################################'
print '### XML'
print '###########################################################################'
print etree.tostring(config_e)
print '###########################################################################'
print '### XML Formatstring'
print '###########################################################################'
print etree.tostring(config_e, pretty_print=True)
print '###########################################################################'
print '### Convert to Dictionary'
print '###########################################################################'
data_dict = xmltodict.parse(etree.tostring(config_e))
print data_dict
print '###########################################################################'
print '### Convert to JSON'
print '###########################################################################'
data_jason = json.dumps(data_dict, indent=4)
print data_jason
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'default'}, look_for_keys=False, allow_agent=False)
print '======================================================================'
print '===== response ====='
print '======================================================================'
response = m.edit_config(config=config_e, default_operation="merge", target="candidate")
print response
response = m.commit()
print response
参考までに、下記が実行結果からXML Formatstring
の出力部分を抽出しています。
###########################################################################
### XML Formatstring
###########################################################################
<config>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
<interface-configuration>
<active>act</active>
<interface-name>GigabitEthernet0/0/0/10</interface-name>
<description>NETCONF configured - 2019-03-18 11:18:27</description>
</interface-configuration>
<interface-configuration>
<active>act</active>
<interface-name>GigabitEthernet0/0/0/11</interface-name>
<description>NETCONF configured - 2019-03-18 11:18:27</description>
</interface-configuration>
</interface-configurations>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"/>
</config>
##interfaceにshutdown
を設定する
###XMLを直書きした場合
#!/usr/bin/env python
from ncclient import manager
from lxml import etree
config = """
<config>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
<interface-configuration>
<active>act</active>
<interface-name>GigabitEthernet0/0/0/10</interface-name>
<shutdown/>
<description>NETCONF configured - shutdown</description>
</interface-configuration>
</interface-configurations>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
<interface-configuration>
<active>act</active>
<interface-name>GigabitEthernet0/0/0/11</interface-name>
<shutdown/>
<description>NETCONF configured - shutdown</description>
</interface-configuration>
</interface-configurations>
</config>
"""
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'default'}, look_for_keys=False, allow_agent=False)
print '======================================================================'
print '===== response ====='
print '======================================================================'
response = m.edit_config(config=config, default_operation="merge", target="candidate").xml
print response
response = m.commit()
print response
##interfaceにno shut
を設定する
###XMLを直書きした場合
#!/usr/bin/env python
from ncclient import manager
from lxml import etree
config = """
<config>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
<interface-configuration>
<active>act</active>
<interface-name>GigabitEthernet0/0/0/10</interface-name>
<shutdown nc:operation="remove"></shutdown>
<description>NETCONF configured - no shutdown</description>
</interface-configuration>
</interface-configurations>
<interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
<interface-configuration>
<active>act</active>
<interface-name>GigabitEthernet0/0/0/11</interface-name>
<shutdown nc:operation="remove"></shutdown>
<description>NETCONF configured - no shutdown</description>
</interface-configuration>
</interface-configurations>
</config>
"""
# connect to netconf agent
m = manager.connect(host='192.168.99.1', port=830, username='cisco', password='cisco', hostkey_verify=False, device_params={'name': 'default'}, look_for_keys=False, allow_agent=False)
print '======================================================================'
print '===== response ====='
print '======================================================================'
response = m.edit_config(config=config, default_operation="merge", target="candidate").xml
print response
response = m.commit()
print response