取消
显示结果 
搜索替代 
您的意思是: 
cancel
513
查看次数
0
有帮助
0
评论
碧云天
Spotlight
Spotlight
一.概述
    可能是因为使用的是eve里面csr1000v的缘故,在用netconfig配置路由器的接口,up接口,并配置ospf时,发现相同的代码,有时执行不成功,有时又能执行成功。代码把功能进行了拆分,分别为配置接口IP、no shutdown接口、配置ospf的router-id、宣告ospf的网络,每执行一个任务都通过netconfig连接路由器的TCP830一次,出现失败的一般都是第一个任务是成功的、后面三个有可能成功,也有可能失败,因此就想着能否把所有的任务集中在一起执行,这样配置一台路由器就只需netconfig连接一次,从而提高效率。
二.解决思路
    经过手工编写payload测试,把接口配置、OSOF配置写在一起,可以正常执行,接下来就是怎么编写模板文件。因为多个接口配置其实是差不多,只是重复代码的问题。查询jinja2的模板可以支持宏,在宏里面还可定义循环语句,后面给宏传参的时候,只需传元素为字典的列表即可。

三.配置步骤(不用sqlite3数据库)
1.创建templates目录,里面放置宏文件和模板文件
①宏文件macro.html分别定义三个宏,用于配置接口ip,up接口,配置ospf,文件内容如下:
{% macro set_if_ip(if_infors) -%}
    {%- for infor in if_infors %}
    <interface>
      <{{ infor.if_type }}>
        <name>{{ infor.if_no }}</name>
        <ip>
          <address>
            <primary>
              <address>{{ infor.if_ip }}</address>
              <mask>{{ infor.mask }}</mask>
            </primary>
          </address>
        </ip>
      </{{ infor.if_type }}>
    </interface>
    {%- endfor %}
 {%- endmacro %}
 {% macro set_if_up(ip_infors) -%}
    {%- for infor in ip_infors %}
    <interface>
      <name>{{ infor.if_type }}{{ infor.if_no }}</name>
      <enabled>true</enabled>
    </interface>
    {%- endfor %}
 {%- endmacro %}
{% macro set_ospf(ospf_infors) -%}
    {%- for infor in ospf_infors %}
    <router>
      <ios-ospf:ospf>
        <ios-ospf:id>{{ infor.process_id }}</ios-ospf:id>
        <ios-ospf:router-id>{{ infor.router_id }}</ios-ospf:router-id>
        <ios-ospf:network>
          <ios-ospf:ip>{{ infor.network }}</ios-ospf:ip>
          <ios-ospf:mask>{{ infor.wild_mask }}</ios-ospf:mask>
          <ios-ospf:area>{{ infor.area }}</ios-ospf:area>
        </ios-ospf:network>
      </ios-ospf:ospf>
    </router>
    {%- endfor %}
 {%- endmacro %}

②模板文件if_and_ospf_config.xml导入前面配置的宏文件,文件内容如下:
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
   <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native" xmlns:ios-ospf="http://cisco.com/ns/yang/Cisco-IOS-XE-ospf">
     {% import "macro.html" as macro %}
     {{ macro.set_if_ip( if_infors ) }}
     {{ macro.set_ospf( ospf_infors ) }}

  </native>
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
     {{ macro.set_if_up( if_infors )}}
  </interfaces>
</config>

2.配置yang_xml_maker_template.py文件,将xml文件转换为jinja2模板,文件内容如下:
from jinja2 import FileSystemLoader, Environment


def netconf_if_and_ospf(if_infs, ospf_infs):
    loader = FileSystemLoader('templates')
    netconf_template = Environment(loader=loader).get_template('if_and_ospf_config.xml')
    return netconf_template.render(if_infors=if_infs, ospf_infors=ospf_infs)

3.配置netconf_request.py文件,使用netconfig连接路由器,文件内容如下:
# -*- coding: utf-8 -*-
import lxml.etree as et
from ncclient import manager
from ncclient.operations import RPCError


def csr_netconf_config(ip, username, password, payload_xml, port='830'):
    with manager.connect(host=ip,
                         port=port,
                         username=username,
                         password=password,
                         timeout=90,
                         hostkey_verify=False,
                         device_params={'name': 'csr'}) as m:

        try:
            response = m.edit_config(target='running', config=payload_xml).xml
            data = et.fromstring(response.encode('utf-8'))
        except RPCError as e:
            data = e._raw
        print(et.tostring(data, pretty_print=True))
4.配置netconf_all_auto.py文件,提供数据;调用yang_xml_maker_template.py中的方法,使用模板,传参给宏,生成request的payload;调用netconf_request.py的方法netconfig连接路由器,执行payload,文件内容如下:

# -*- coding: utf-8 -*-
from netconf_request import csr_netconf_config
from yang_xml_maker_template import netconf_if_and_ospf

csr1_ifs = [{'if_type': 'GigabitEthernet', 'if_no': '1', 'if_ip': '137.78.5.1', 'mask': '255.255.255.0'},
            {'if_type': 'GigabitEthernet', 'if_no': '2', 'if_ip': '61.128.1.1', 'mask': '255.255.255.0'},
            {'if_type': 'Loopback', 'if_no': '0', 'if_ip': '1.1.1.1', 'mask': '255.255.255.0'}]

csr2_ifs = [{'if_type': 'GigabitEthernet', 'if_no': '1', 'if_ip': '61.128.1.2', 'mask': '255.255.255.0'},
            {'if_type': 'GigabitEthernet', 'if_no': '2', 'if_ip': '202.100.1.2', 'mask': '255.255.255.0'},
            {'if_type': 'Loopback', 'if_no': '0', 'if_ip': '2.2.2.2', 'mask': '255.255.255.0'}]

csr1_ospf = [{'process_id': '1', 'router_id': '1.1.1.1', 'network': '137.78.5.1', 'wild_mask': '0.0.0.0', 'area': '0'},
             {'process_id': '1', 'router_id': '1.1.1.1', 'network': '61.128.1.1', 'wild_mask': '0.0.0.0', 'area': '0'}]

csr2_ospf = [{'process_id': '1', 'router_id': '2.2.2.2', 'network': '202.100.1.2', 'wild_mask': '0.0.0.0', 'area': '0'},
             {'process_id': '1', 'router_id': '2.2.2.2', 'network': '61.128.1.2', 'wild_mask': '0.0.0.0', 'area': '0'}]

all_network_data = [{'ip': '192.168.10.100', 'interface': csr1_ifs, 'ospf': csr1_ospf},
                    {'ip': '192.168.10.200', 'interface': csr2_ifs, 'ospf': csr2_ospf}]

username = 'admin'
password = 'Cisc0123'


def netconf_all_auto():
    for csr in all_network_data:
        print('配置接口IP和OSPF')
        csr_netconf_config(csr['ip'], username, password, netconf_if_and_ospf(csr['interface'], csr['ospf']), port='830')


if __name__ == '__main__':
    netconf_all_auto()
四.配置步骤(使用sqlite3数据库)
1.创建templates目录,里面放置宏文件和模板文件
2.配置yang_xml_maker_template.py文件,将xml文件转换为jinja2模板
3.配置netconf_request.py文件,使用netconfig连接路由器,
---这三步与前面相同
4.添加database目录,并创建使用SQLite驱动的netconf.db数据库文件,通过如下sql建表,并插入数据
drop table router_infor;
create table router_infor
(
    [router_id] integer PRIMARY KEY AUTOINCREMENT,
    [ip] varchar,
    [login_name] varchar,
    [login_passwd] varchar
);

insert into router_infor values  (null,'192.168.10.100','admin','Cisc0123');
insert into router_infor values  (null,'192.168.10.200','admin','Cisc0123');

drop table interface_infors;
create table interface_infors(
    id integer,
    if_type varchar,
    if_no integer,
    if_ip varchar,
    mask varchar,
    foreign key (id) references router_infor(router_id)
);
insert into interface_infors values (1,'GigabitEthernet', 1, '137.78.5.1', '255.255.255.0');
insert into interface_infors values (1,'GigabitEthernet', 2, '61.128.1.1', '255.255.255.0');
insert into interface_infors values (1,'Loopback', 0, '1.1.1.1', '255.255.255.255');
insert into interface_infors values (2,'GigabitEthernet', 1, '61.128.1.2', '255.255.255.0');
insert into interface_infors values (2,'GigabitEthernet', 2, '202.100.1.2', '255.255.255.0');
insert into interface_infors values (2,'Loopback', 0, '2.2.2.2', '255.255.255.255');

drop table  ospf_infors;
create table ospf_infors
(
    id integer,
    process_id integer,
    router_id varchar,
    network varchar,
    wild_mask varchar,
    area integer,
    foreign key (id) references router_infor (router_id)
);
insert into ospf_infors values (1,1, '1.1.1.1', '137.78.5.1', '0.0.0.0', 0);
insert into ospf_infors values (1,1, '1.1.1.1', '61.128.1.1', '0.0.0.0', 0);
insert into ospf_infors values (2,1, '2.2.2.2', '61.128.1.2', '0.0.0.0', 0);
insert into ospf_infors values (2,1, '2.2.2.2', '202.100.1.2', '0.0.0.0', 0);

4.配置netconf_all_auto.py文件,文件内容如下:
from netconf_request import csr_netconf_config
from yang_xml_maker_template import netconf_if_and_ospf
import sqlite3


def dict_factory(cursor, row): 
# 定义方法,查询数据库,返回字典
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d


def netconf_all_auto():
    con = sqlite3.connect("./database/netconf.db")
    con.row_factory = dict_factory
    cur = con.cursor()
    sql = cur.execute("select * from router_infor").fetchall()
    for csr in sql:
        print('配置接口IP和OSPF')
        int_infors = cur.execute("select * from interface_infors where id = {}".format(csr['router_id'])).fetchall()
        ospf_infors = cur.execute("select * from ospf_infors where id = {}".format(csr['router_id'])).fetchall()
        payload = netconf_if_and_ospf(int_infors, ospf_infors)
        csr_netconf_config(csr['ip'], csr['login_name'], csr['login_passwd'], payload, port='830')


if __name__ == '__main__':
    netconf_all_auto()


五.验证效果
经过实际测试,每次都能成功执行。
入门指南

使用上面的搜索栏输入关键字、短语或问题,搜索问题的答案。

我们希望您在这里的旅程尽可能顺利,因此这里有一些链接可以帮助您快速熟悉思科社区: