使用 Junos PyEZ 配置表在 Junos 设备上配置结构化资源
指定属性的 set
Junos PyEZ 配置表和视图允许您定义可用于以编程方式配置 Junos 设备的结构化资源。在将结构化资源的表定义加载或导入 Junos PyEZ 应用程序后,应用程序可以在您的设备上配置资源。本主题讨论使用 Junos PyEZ 配置表和视图在设备上配置结构化资源的常规流程和一些具体任务。
常规配置流程
配置表 set
属性可标识配置资源的配置层次结构级别,并设置视图中字段的 XPath 上下文。例如,下表定义层次 user
结构级别的 [edit system login]
资源:
UserConfigTable: set: system/login/user key-field: username view: UserConfigView UserConfigView: groups: auth: authentication fields: username: name userclass: { class : { 'default' : 'unauthorized' }} uid: { uid: { 'type': 'int', 'default':1001, 'minValue':100, 'maxValue':64000 }} fullname: full-name fields_auth: password: encrypted-password
View 中包含的字段定义了用户可为该资源配置的叶语句。字段可以定义默认值以及类型和约束检查。
要在设备上配置结构化资源,必须将表加载或导入应用程序中。然后,您可以创建一个表对象,然后将其与 Device
代表目标设备的对象相关联。例如:
from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable from lxml import etree import crypt with Device(host='router.example.com') as dev: uc = UserConfigTable(dev)
要定义资源配置语句的值,请将相应的字段名称(如 视图中定义)设置为等于所需的值。
table_object.fieldname = value
除非 View 明确定义该字段的默认值,否则字段的默认值是 None
。如果 View 定义字段的类型或约束检查,则应用程序必须为该字段提供正确的数据类型和值,并且理想情况下处理在检查失败时可能提出的任何错误。您必须始终定义表资产中声明的任何关键字段的 key-field
值,在此示例中为 username
。
以下代码导入UserConfigTable
和配置的、和password
字段的username
userclass
值。该crypt
模块计算配置的用户密码的哈希。此示例要求 Python3 使用该crypt()
功能与单个论点。
# Python 3 from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable from lxml import etree import crypt with Device(host='router.example.com') as dev: uc = UserConfigTable(dev) uc.username = 'user1' uc.userclass = 'operator' uc.password = crypt.crypt('lab123') ...
有关更具体的配置任务的详细信息,如使用固定格式关键字或多个值配置语句、配置语句或资源的多个实例、删除叶或容器语句或配置与 Junos XML 属性对应的对象属性,请参阅以下部分:
配置对象后,必须调用 append()
构建相应 Junos XML 配置的方法,并将其 lxml
添加到存储该表对象的主配置更改集的对象中。配置更改仅包括在视图中定义默认值或用户配置的值的字段。保留其初始值的 None
字段将被忽略。
uc.append()
构建 XML 之后, append()
该方法还会将所有字段重置为其默认值,或者 None
如果 View 未为该字段定义默认值。这使您能够在同一应用程序中配置多个对象,并确保在配置后续资源时不会无意中使用为一个资源定义的价值。每次配置新资源时,都必须调用 append()
为主要更改集添加配置更改。有关该方法的 append()
详细信息,请参阅 使用附录 () 生成 Junos XML 配置数据。
如有必要,您还可以通过调用 reset()
此方法手动重置表对象的所有字段。
uc.reset()
此 reset()
方法可将所有字段恢复为其默认值,或者 None
如果视图未定义默认值。此 reset()
方法仅重置字段的当前值。它不会影响 XML,其中包含通过调用方法 append()
构建到该点的配置更改。
您可通过致电 get_table_xml()
该方法检索表示应用程序中任何点更改的 XML 配置,该方法在 “查看您的配置更改”中进行了详细讨论。
configXML = uc.get_table_xml() if (configXML is not None): print (etree.tostring(configXML, encoding='unicode', pretty_print=True))
配置所有必要的对象并拨打电话 append()
后,可使用两种方法之一将配置更改加载到设备上的共享配置数据库:
set()
呼叫方法,自动调用lock()
、load()
、commit()
和unlock()
方法lock()
单独调用、load()
、commit()
和unlock()
方法
uc.set()
使用包含mode
使用特定配置模式的参数的上下文管理器 (with ... as
语法)创建表实例时,上下文管理器将处理开口、锁定和关闭以及解锁数据库。在这种情况下,您只需要调用配置设备的调用load()
和commit()
方法。lock()
呼叫或set()
方法会导致例外LockError
。
使用单一 set()
方法可提供简单性,但呼叫单个方法可提供额外的灵活性,例如,在加载配置数据之后,需要调用其他方法,但在提交之前。例如,在加载数据之后,但在提交数据之前,您可能需要调用 diff()
或 pdiff()
方法来查看配置差异。或者,您可能需要调用 rollback()
此方法,将候选配置重置回活动配置,而不是提交。有关使用不同方法加载和提交配置数据的详细信息,请参阅 使用 Junos PyEZ 配置 Junos 设备 并 使用 Junos PyEZ 提交配置。
对于可能超时的大负载和提交操作,您可以通过在或commit()
方法论证列表中set()
包括timeout
参数来调整 RPC 超时间隔。有关更多信息,请参阅 如何控制 RPC 超时间隔。
指定参数的 set
配置表为超级集,并具有指定 get
参数的配置表的所有功能。您可以在 Junos PyEZ 应用程序中以相同的方式检索配置数据,无论表是 set
指定还是 get
。有关使用配置表检索配置数据的信息,请参阅 使用 Junos PyEZ 配置表检索配置数据。
配置由固定格式关键字组成的语句
叶语句是 CLI 配置语句,不包含任何其他语句。大多数叶语句定义配置对象的一个特征的值,并具有以下形式:
keyword value;
某些叶语句仅包含固定格式的关键字,而没有关联的可变形式值。例如, ftp
层次结构级别上的 [edit system services]
语句是固定格式关键字的示例。
system { services { ftp; } }
Junos XML API 使用空标记表示此类语句。
<configuration> <system> <services> <ftp> </ftp> ... </services> </system> </configuration>
要在 Junos PyEZ 应用程序中配置固定格式的关键字(例如下方[edit system services]
的ftp
语句),请将视图中定义的相应字段名称的值设置为等于布尔值True
。
请考虑以下视图,该 ftp
视图定义了类型约束的字段,以确保字段的值为布尔:
ServicesView: fields: ftp: { 'ftp' : { 'type': 'bool' } } ...
要在 Junos PyEZ 应用程序中配置 ftp
字段,请将字段设置为等 True
于 。
from jnpr.junos import Device from myTables.ConfigTables import ServicesConfigTable with Device(host='router.example.com') as dev: sc = ServicesConfigTable(dev) sc.ftp = True sc.append() sc.set()
为同一语句配置多个值
某些 Junos OS 叶语句接受多个值,这些值可能是用户定义的,也可以是从一组预定义的值中提取的。CLI 符号使用方括号在单个语句中将所有值括起来,如下列所示:
keyword [ value1 value2 value3 ...];
例如,您可能需要为中继接口配置 VLAN ID 列表,如以下配置所示:
interfaces { ge-0/0/1 { native-vlan-id 510; unit 0 { family bridge { interface-mode trunk; vlan-id-list [ 510 520 530 ]; } } } }
要在 Junos PyEZ 应用程序中配置具有多个值的叶语句,请将对应字段的值(如 视图中定义)等同于包含所需值的 Python 列表。在以下示例中 vlan_list
,字段映射到 vlan-id-list
CLI 中的语句。要使用多个 VLAN ID 配置语句,请将字段名称设置为等于 ID 列表。
from jnpr.junos import Device from myTables.ConfigTables import InterfacesConfigTable with Device(host='router.example.com') as dev: intf = InterfacesConfigTable(dev) intf.name = 'ge-0/0/1' intf.mode = 'trunk' intf.native_vlan = 510 intf.vlan_list = [510, 520, 530] intf.append() intf.set()
您用于 Junos PyEZ 应用程序中的字段值的 Python 列表是逗号划定的值列表。这不同于您将在 CLI 中配置的空间划定列表。
配置相同语句的多个实例
在某些情况下,Junos OS 配置允许您配置相同语句的多个实例。例如,您可以在同一协议家族下为逻辑接口配置多个地址。在以下配置片段中,环路接口在层次结构级别上配置了 [edit interfaces lo0 unit 0 family inet]
多个地址:
interfaces { lo0 { unit 0 { family inet { address 192.168.100.1/32; address 192.168.100.2/32; } } } }
配置的 Junos XML 表示如下:
<configuration> <interfaces> <interface> <name>lo0</name> <unit> <name>0</name> <family> <inet> <address> <name>192.168.100.1/32</name> </address> <address> <name>192.168.100.2/32</name> </address> </inet> </family> </unit> </interface> </interfaces> </configuration>
使用 Junos PyEZ 配置表管理结构化资源时,可通过将相应的字段名称设置为等于所需值来定义配置语句的值。但是,您不能在 Junos PyEZ 应用程序中定义同一字段两次,因为第二个值将覆盖第一个值。相反,您必须将字段设置为等于一个值列表,而 Junos PyEZ 则处理转换为 XML。
考虑以下表和视图:
InterfaceTable: set: interfaces/interface key-field: - name - unit_name view: InterfaceView InterfaceView: fields: name: name desc: description unit_name: unit/name ip_address: unit/family/inet/address
以下示例代码说明了如何为 Junos PyEZ 应用程序中的环路接口配置多个地址。在这种情况下,您将字段设置 ip_address
为等于一个地址列表。
lo0_addresses = ['192.168.100.1/32', '192.168.100.2/32'] ... intf = InterfaceTable(dev) intf.name='lo0' intf.unit_name = 0 intf.ip_address = lo0_addresses intf.append() intf.set() ...
生成的配置是:
[edit interfaces] + lo0 { + unit 0 { + family inet { + address 192.168.100.1/32; + address 192.168.100.2/32; + } + } + }
配置相同资源的多个实例
使用 Junos PyEZ 配置表配置结构化资源时,可能需要为同一资源配置多个对象或记录。例如,您可以同时配置多个接口或用户。要为 Junos PyEZ 应用程序中的相同结构化资源配置多个对象,必须定义一个对象字段的值,调用 append()
此方法,然后为每个后续对象重复此过程。
例如,要配置多个用户,请定义第一个用户的字段值,然后调用 append()
此方法。然后定义第二个用户的字段值,然后调用 append()
该方法。该 append()
方法会为配置更改构建 Junos XML 数据,并将其 lxml
添加到存储主要配置更改集的对象中。该方法还会自动将所有字段重置为其默认值(如“视图”中定义),或者 None
如果字段没有定义的默认值。
以下示例配置两个用户对象并提交更改:
from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable from lxml import etree import crypt with Device(host='router.example.com') as dev: uc = UserConfigTable(dev) uc.username = 'user1' uc.userclass = 'operator' uc.uid = 1005 uc.password = crypt.crypt('lab123') uc.append() uc.username = 'user2' uc.userclass = 'operator' uc.uid = 1006 uc.password = crypt.crypt('lab456') uc.append() uc.set()
如果在为相同资源配置多个对象之一后未调用 append()
此方法,则第二个对象的字段值将覆盖第一个对象的字段值。
以下示例代码使用更紧凑的语法配置相同的两个用户:
from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable from lxml import etree import crypt users = ['user1', 'user2'] uids = ['1005', '1006'] passwds = ['lab123', 'lab456'] with Device(host='router.example.com') as dev: uc = UserConfigTable(dev) for user, uid, passwd in zip(users, uids, passwds): uc.username = user uc.userclass = 'operator' uc.uid = uid uc.password = crypt.crypt(passwd) uc.append() uc.set()
删除容器或叶语句
在某些情况下,您可能需要删除配置中的容器或叶语句。使用 Junos PyEZ 配置表管理结构化资源时,可在应用程序中执行此操作,方法是将相应的字段值设置为 {'operation' : 'delete'}
。删除容器或叶语句时,您必须始终定义所有关键字段的值,以指示删除应用的对象。
考虑以下 Junos PyEZ 配置表和视图:
--- UserConfigTable2: set: system/login key-field: - username view: UserConfigView2 UserConfigView2: groups: auth: user/authentication fields: user: user username: user/name classname: { user/class : { 'type' : { 'enum' : ['operator', 'read-only', 'super-user'] } } } uid: { user/uid : { 'type' : 'int', 'minValue' : 100, 'maxValue' : 64000 } } fields_auth: password: encrypted-password
要删除表和视图中定义的资源的叶语句,请将该语句对应的字段值设置为 {'operation' : 'delete'}
。以下示例删除了 uid
用户 jsmith
语句:
from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable2 with Device(host='router.example.com') as dev: uc = UserConfigTable2(dev) uc.username = 'jsmith' uc.uid = { 'operation' : 'delete' } uc.append() uc.set()
要从配置中删除容器,View 必须为该容器定义字段。在表和视图中,属性定义的 set
配置范围为 system/login
。视图定义了该字段“user
,该字段将映射到 system/login/user
容器。如有必要,此定义允许您删除用户对象。如果不为容器定义字段,则只能删除容器内的语句,但无法删除容器本身。
要删除 Junos PyEZ 应用程序中的容器,请将字段的值设置为 {'operation' : 'delete'}
对应于容器的字段,然后定义密钥字段以指示要删除的对象。以下示例从配置中删除用户 jsmith
:
from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable2 from lxml import etree with Device(host='router.example.com') as dev: uc = UserConfigTable2(dev) uc.user = { 'operation' : 'delete' } uc.username = 'jsmith' uc.append() print (etree.tostring(uc.get_table_xml(), encoding='unicode', pretty_print=True)) uc.set()
该应用程序将打印该方法返回的 get_table_xml()
Junos XML 配置数据。标识符“jsmith”的用户元素包括一个属性, operation="delete"
用于指示 Junos OS 从配置中卸下该对象。
<configuration> <system> <login> <user operation="delete"> <name>jsmith</name> </user> </login> </system> </configuration>
配置与 Junos XML 属性对应的属性
例如deactivate
protect
,某些配置模式命令将特定属性(如非活动或保护属性)应用或移除到配置语句中。在 CLI 中,此属性由配置语句前面的标记表示。Junos XML 配置表示此属性对对象使用 XML 属性。
例如,以下命令会停用给定的接口。
[edit] user@host# deactivate interfaces ge-1/0/2
在 CLI 中查看配置时, inactive
标记在接口名称之前。
[edit] user@host# show interfaces inactive: ge-1/0/2 { description "to CustomerA"; unit 0 { family inet { address 198.51.100.1/24; } } }
同样,在 Junos XML 输出中, <interface>
相同接口的元素也包含 inactive="inactive"
属性。
user@host# show interfaces | display xml <rpc-reply xmlns:junos="http://xml.juniper.net/junos/18.3R1/junos"> <configuration junos:changed-seconds="1544581124" junos:changed-localtime="2018-12-11 18:18:44 PST"> <interfaces> <interface inactive="inactive"> <name>ge-1/0/2</name> <description>to CustomerA</description> <unit> <name>0</name> <family> <inet> <address> <name>198.51.100.1/24</name> </address> </inet> </family> </unit> </interface> </interfaces> </configuration> </rpc-reply>
Junos PyEZ 配置表允许您在配置结构化资源时为对象定义支持的 XML 属性。考虑以下 Junos PyEZ 配置表和视图:
InterfaceTable: set: interfaces key-field: - name view: InterfaceView InterfaceView: fields: interface: interface name: interface/name desc: interface/description unit_name: interface/unit/name ip_address: interface/unit/family/inet/address
要为给定的配置对象定义 XML 属性,请将其字段(如视图定义)设置为包含属性及其值的字典。例如,要定义接口,但要立即停用,请将字段对应于该 <interface>
元素 {'inactive':'inactive'}
。以下示例配置并停用给定的接口:
from jnpr.junos import Device from myTables.ifConfigTable import InterfaceTable from lxml import etree with Device(host='router.example.com') as dev: intf = InterfaceTable(dev) intf.name = 'ge-1/0/2' intf.unit_name = 0 intf.ip_address = '198.51.100.1/24' intf.desc = 'to CustomerA' intf.interface = {'inactive':'inactive'} intf.append() configXML = intf.get_table_xml() if (configXML is not None): print (etree.tostring(configXML, encoding='unicode', pretty_print=True)) else: print (configXML) intf.set()
该应用程序将打印该方法返回的 get_table_xml()
Junos XML 配置数据。标识符“ge-1/0/2”的接口元素包括 inactive="inactive"
属性。
<configuration> <interfaces> <interface inactive="inactive"> <name>ge-1/0/2</name> <unit> <name>0</name> <family> <inet> <address>198.51.100.1/24</address> </inet> </family> </unit> <description>to CustomerA</description> </interface> </interfaces> </configuration>
要激活非活动对象,请将视图字段对应于非活动对象 {'active':'active'}
。
from jnpr.junos import Device from myTables.ifConfigTable import InterfaceTable from lxml import etree with Device(host='router.example.com') as dev: intf = InterfaceTable(dev) intf.name = 'ge-1/0/2' intf.interface = {'active':'active'} intf.append() intf.set()
同样,要保护配置元素或从受保护元素中 protect
移除属性,请将相应的字段值设置为 {'protect':'protect'}
或 {'unprotect':'unprotect'}
。有关 Junos OS 配置中的 XML 属性的详细信息,请参阅 Junos XML 管理协议开发人员指南 。
使用附录 () 生成 Junos XML 配置数据
使用 Junos PyEZ 配置表配置结构化资源时,定义资源字段的值,然后调用 append()
此方法。对该方法的 append()
每个调用都会生成当前更改集的 Junos XML 配置数据,并将其 lxml
添加到存储主配置更改集的对象中。
from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable import crypt with Device(host='router.example.com') as dev: uc = UserConfigTable(dev) uc.username = 'user1' uc.userclass = 'operator' uc.password = crypt.crypt('lab123') uc.append() uc.set()
append()
调用此方法可为您的资源生成 Junos XML 配置数据。配置更改仅包括在视图中定义默认值或用户配置的值的字段。保留其初始值的None
字段将被忽略。
构建 XML 之后,append()
该方法还会将所有字段重置为其默认值(如 View 中定义),或者如果None
字段没有定义的默认值。重置字段可确保,当在同一应用程序中配置多个对象时,不会为一个对象设置字段值,然后在后续对append()
不同对象的调用中无意中使用该值。因此,您必须为每个通话append()
的所有key-field
字段定义新的值。
将附录节点附加到主要配置更改集后,便无法撤消操作。
该append()
方法仅将新更改添加至lxml
包含主配置更改集的对象。您必须明确地调用在set()
设备上加载和提交更改的方法或load()
commit()
方法。
查看您的配置更改
使用 Junos PyEZ 配置表配置结构化资源时,定义资源字段的值,然后调用 append()
此方法。对该方法的 append()
每个调用都会生成当前更改集的 Junos XML 配置数据,并将其 lxml
添加到存储主配置更改集的对象中。有时,您可能需要查看应用程序中某个点构建的配置数据,或者可能需要在将配置更改加载到设备上之后查看候选配置和活动配置之间的差异。
要检索包含更改的 Junos XML 配置数据,请使用表对象 get_table_xml()
的方法。该 get_table_xml()
方法将构建到应用程序中该点的 XML 配置返回。当您调用 set()
该方法或 load()
方法 commit()
时,应用程序会在设备上加载并提交此 Junos XML 配置数据。
以下示例会调用 get_table_xml()
检索配置更改的方法,然后将其存储在变量中 configXML
。在调用 append()
此方法之前, get_table_xml()
方法会返回 None
。因此,应用程序仅对 XML 配置数据进行串行化和打印,如果返回的值不是 None
。
from jnpr.junos import Device from myTables.ConfigTables import UserConfigTable from lxml import etree import crypt with Device(host='router.example.com') as dev: uc = UserConfigTable(dev) uc.username = 'user1' uc.userclass = 'operator' uc.password = crypt.crypt('lab123') uc.append() configXML = uc.get_table_xml() if (configXML is not None): print (etree.tostring(configXML, encoding='unicode', pretty_print=True)) else: print (configXML) uc.set()
此 get_table_xml()
方法仅返回用于配置更改的 Junos XML 数据。您可能需要在将配置更改加载到设备上之后比较候选配置和活动配置,以便在提交更改之前查看差异。
要检索差异,您可以在加载数据之后(但在提交数据之前)呼叫该方法,以便单独调用lock()
、unlock()
load()
commit()
和方法并查看配置差异。pdiff()
空pdiff()
参数列表的方法将候选配置与活动配置进行比较,然后将补丁格式的差异直接打印到标准输出。
... uc.append() uc.lock() uc.load() uc.pdiff() ... uc.commit() uc.unlock()
如何控制 RPC 超时间隔
使用 Junos PyEZ 配置表配置结构化资源时,可通过调用set()
方法或load()
commit()
方法来加载和提交配置更改。这些set()
和commit()
方法使用模块中定义的 device
RPC 超时值。如果不为Device
timeout
该属性配置新值,Junos PyEZ 将使用 30 秒的默认值。
大型配置更改可能超过默认或配置的超时值,导致操作超时,然后才能在设备上传和提交配置。要适应可能需要比默认或配置的超时间隔更长的负载和提交时间的某些配置更改,请在您调用应用程序或commit()
方法时将set()
该参数设置timeout=seconds
为适当的值。例如:
uc = UserConfigTable(dev) uc.username = 'user1' uc.userclass = 'operator' uc.uid = 1005 uc.password = crypt.crypt('lab123') uc.append() uc.set(timeout=300)