Ejemplo: Personalizar la salida del comando show interfaces concisas mediante un script de operación
En este ejemplo se utiliza un script op para personalizar la salida del show interfaces terse
comando. Se proporciona una explicación línea por línea del script XSLT.
Requisitos
En este ejemplo se utiliza un dispositivo que ejecuta Junos OS.
Descripción general y script de operación
De forma predeterminada, el diseño del show interfaces terse
comando tiene este aspecto:
user@host> show interfaces terse Interface Admin Link Proto Local Remote dsc up up fxp0 up up fxp0.0 up up inet 192.168.71.246/21 fxp1 up up fxp1.0 up up inet 10.0.0.4/8 inet6 fe80::200:ff:fe00:4/64 fc00::10:0:0:4/64 tnp 4 gre up up ipip up up lo0 up up lo0.0 up up inet 127.0.0.1 --> 0/0 lo0.16385 up up inet inet6 fe80::2a0:a5ff:fe12:2f04 lsi up up mtun up up pimd up up pime up up tap up up
En Junos XML, los campos de salida se representan de la siguiente manera:
user@host> show interfaces terse | display xml <rpc-reply xmlns:junos="http://xml.juniper.net/junos/10.0R1/junos"> <interface-information xmlns="http://xml.juniper.net/junos/10.0R1/junos-interface" junos:style="terse"> <physical-interface> <name>dsc</name> <admin-status>up</admin-status> <oper-status>up</oper-status> </physical-interface> <physical-interface> <name>fxp0</name> <admin-status>up</admin-status> <oper-status>up</oper-status> <logical-interface> <name>fxp0.0</name> <admin-status>up</admin-status> <oper-status>up</oper-status> ... Remainder of output omitted for brevity ...
Sintaxis XSLT
La siguiente secuencia de comandos personaliza el resultado del show interfaces terse
comando. Se proporciona una explicación línea por línea del guión.
1 <?xml version="1.0" standalone="yes"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:junos="http://xml.juniper.net/junos/*/junos" 5 xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" 6 xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0"> 7 <xsl:import href="../import/junos.xsl"/> 8 <xsl:variable name="arguments"> 9 <argument> 10 <name>interface</name> 11 <description>Name of interface to display</description> 12 </argument> 13 <argument> 14 <name>protocol</name> 15 <description>Protocol to display (inet, inet6)</description> 16 </argument> 17 </xsl:variable> 18 <xsl:param name="interface"/> 19 <xsl:param name="protocol"/> 20 <xsl:template match="/"> 21 <op-script-results> 22 <xsl:variable name="rpc"> 23 <get-interface-information> 24 <terse/> 25 <xsl:if test="$interface"> 26 <interface-name> 27 <xsl:value-of select="$interface"/> 28 </interface-name> 29 </xsl:if> 30 </get-interface-information> 31 </xsl:variable> 32 <xsl:variable name="out" select="jcs:invoke($rpc)"/> 33 <interface-information junos:style="terse"> 34 <xsl:choose> 35 <xsl:when test="$protocol='inet' or $protocol='inet6' or $protocol='mpls' or $protocol='tnp'"> 36 <xsl:for-each select="$out/physical-interface/ logical-interface[address-family/address-family-name = $protocol]"> 37 <xsl:call-template name="intf"/> 38 </xsl:for-each> 39 </xsl:when> 40 <xsl:when test="$protocol"> 41 <xnm:error> 42 <message> 43 <xsl:text>invalid protocol: </xsl:text> 44 <xsl:value-of select="$protocol"/> 45 </message> 46 </xnm:error> 47 </xsl:when> 48 <xsl:otherwise> 49 <xsl:for-each select="$out/physical-interface/logical-interface"> 50 <xsl:call-template name="intf"/> 51 </xsl:for-each> 52 </xsl:otherwise> 53 </xsl:choose> 54 </interface-information> 55 </op-script-results> 56 </xsl:template> 57 <xsl:template name="intf"> 58 <xsl:variable name="status"> 59 <xsl:choose> 60 <xsl:when test="admin-status='up' and oper-status='up'"> 61 <xsl:text> </xsl:text> 62 </xsl:when> 63 <xsl:when test="admin-status='down'"> 64 <xsl:text>offline</xsl:text> 65 </xsl:when> 66 <xsl:when test="oper-status='down' and ../admin-status='down'"> 67 <xsl:text>p-offline</xsl:text> 68 </xsl:when> 69 <xsl:when test="oper-status='down' and ../oper-status='down'"> 70 <xsl:text>p-down</xsl:text> 71 </xsl:when> 72 <xsl:when test="oper-status='down'"> 73 <xsl:text>down</xsl:text> 74 </xsl:when> 75 <xsl:otherwise> 76 <xsl:value-of select="concat(oper-status, '/', admin-status)"/> 77 </xsl:otherwise> 78 </xsl:choose> 79 </xsl:variable> 80 <xsl:variable name="desc"> 81 <xsl:choose> 82 <xsl:when test="description"> 83 <xsl:value-of select="description"/> 84 </xsl:when> 85 <xsl:when test="../description"> 86 <xsl:value-of select="../description"/> 87 </xsl:when> 88 </xsl:choose> 89 </xsl:variable> 90 <logical-interface> 91 <name><xsl:value-of select="name"/></name> 92 <xsl:if test="string-length($desc)"> 93 <admin-status><xsl:value-of select="$desc"/></admin-status> 94 </xsl:if> 95 <admin-status><xsl:value-of select="$status"/></admin-status> 96 <xsl:choose> 97 <xsl:when test="$protocol"> 98 <xsl:copy-of select="address-family[address-family-name = $protocol]"/> 99 </xsl:when> 100 <xsl:otherwise> 101 <xsl:copy-of select="address-family"/> 102 </xsl:otherwise> 103 </xsl:choose> 104 </logical-interface> 105 </xsl:template> 106 </xsl:stylesheet>
Explicación línea por línea
Las líneas 1 a 7, 20 y 105 y 106 son las repetitivas que incluye en cada script op. Para obtener más información, consulte Boilerplate requerido para scripts operativos.
1 <?xml version="1.0" standalone="yes"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:junos="http://xml.juniper.net/junos/*/junos" 5 xmlns:xnm="http://xml.juniper.net/xnm/1.1/xnm" 6 xmlns:jcs="http://xml.juniper.net/junos/commit-scripts/1.0"> 7 <xsl:import href="../import/junos.xsl"/> ... 20 <xsl:template match="/"> ... 105 </xsl:template> 106 </xsl:stylesheet>
Las líneas 8 a 17 declaran una variable llamada arguments
, que contiene dos argumentos para el script: interface
y protocol
. Esta declaración de variable hace que interface
y protocol
aparezca en la interfaz de línea de comandos (CLI) como argumentos disponibles para el script.
8 <xsl:variable name="arguments"> 9 <argument> 10 <name>interface</name> 11 <description>Name of interface to display</description> 12 </argument> 13 <argument> 14 <name>protocol</name> 15 <description>Protocol to display (inet, inet6)</description> 16 </argument> 17 </xsl:variable>
Las líneas 18 y 19 declaran dos parámetros para el script, correspondientes a los argumentos creados en las líneas 8 a 17. Los nombres de los parámetros deben coincidir exactamente con los nombres de los argumentos.
18 <xsl:param name="interface"/> 19 <xsl:param name="protocol"/>
Las líneas 20 a 31 declaran una variable denominada rpc
. El show interfaces terse
comando se asigna a la rpc
variable. Si incluye el argumento al ejecutar el script, el valor del argumento (el interface
nombre de la interfaz) se pasa al script.
20 <xsl:template match="/"> 21 <op-script-results> 22 <xsl:variable name="rpc"> 23 <get-interface-information> 24 <terse/> 25 <xsl:if test="$interface"> 26 <interface-name> 27 <xsl:value-of select="$interface"/> 28 </interface-name> 29 </xsl:if> 30 </get-interface-information> 31 </xsl:variable>
La línea 32 declara una variable nombrada out
y le aplica la ejecución de la rpc
variable (show interfaces terse
command).
32 <xsl:variable name="out" select="jcs:invoke($rpc)"/>
La línea 33 especifica que el nivel de salida del show interfaces
comando que se modifica es terse
(en contraposición a extensive
, , detail
y así sucesivamente).
33 <interface-information junos:style="terse">
Las líneas 34 a 39 especifican que si incluye el argumento al ejecutar el script y si el protocol
valor de protocolo que especifica es inet
, , , mpls
o tnp
, inet6
la plantilla se aplica a cada instancia de ese tipo de protocolo en la intf
salida.
34 <xsl:choose> 35 <xsl:when test="$protocol='inet' or $protocol='inet6' or $protocol='mpls' or $protocol='tnp'"> 36 <xsl:for-each select="$out/physical-interface/ logical-interface[address-family/address-family-name = $protocol]"> 37 <xsl:call-template name="intf"/> 38 </xsl:for-each> 39 </xsl:when>
Las líneas 40 a 47 especifican que si incluye el argumento al ejecutar la secuencia de comandos y si el protocol
valor de protocolo que especifica es distinto de , , mpls
o tnp
, inet6
se genera un mensaje de inet
error.
40 <xsl:when test="$protocol"> 41 <xnm:error> 42 <message> 43 <xsl:text>invalid protocol: </xsl:text> 44 <xsl:value-of select="$protocol"/> 45 </message> 46 </xnm:error> 47 </xsl:when>
Las líneas 48 a 52 especifican que si no incluye el argumento al ejecutar el protocol
script, la plantilla se aplica a cada interfaz lógica de la intf
salida.
48 <xsl:otherwise> 49 <xsl:for-each select="$out/physical-interface/logical-interface"> 50 <xsl:call-template name="intf"/> 51 </xsl:for-each> 52 </xsl:otherwise>
Las líneas 53 a 56 son etiquetas de cierre.
53 </xsl:choose> 54 </interface-information> 55 </op-script-results> 56 </xsl:template>
La línea 57 abre la intf
plantilla. Esta plantilla personaliza la salida del show interfaces terse
comando.
57 <xsl:template name="intf">
La línea 58 declara una variable denominada status
, cuyo propósito es especificar cómo se informa del estado de la interfaz. Las líneas 59 a 78 contienen una <xsl:choose>
instrucción que rellena la status
variable considerando todos los estados posibles. Como siempre en XSLT, se ejecuta la primera <xsl:when>
instrucción que se evalúa como TRUE y el resto se ignora. Cada <xsl:when>
instrucción se explica por separado.
58 <xsl:variable name="status"> 59 <xsl:choose>
Las líneas 60 a 62 especifican que si admin-status
está "arriba" y oper-status
está "arriba", no se genera ningún resultado. En este caso, la status
variable permanece vacía.
60 <xsl:when test="admin-status='up' and oper-status='up'"> 61 <xsl:text> </xsl:text> 62 </xsl:when>
Las líneas 63 a 65 especifican que si admin-status
está 'abajo', la status
variable contiene el texto offline
.
63 <xsl:when test="admin-status='down'"> 64 <xsl:text>offline</xsl:text> 65 </xsl:when>
Las líneas 66 a 68 especifican que si oper-status
está "inactiva" y la interfaz admin-status
física está "inactiva", la status
variable contiene el texto p-offline
. ../
( selecciona la interfaz física.)
66 <xsl:when test="oper-status='down' and ../admin-status='down'"> 67 <xsl:text>p-offline</xsl:text> 68 </xsl:when>
Las líneas 69 a 71 especifican que si oper-status
está "inactiva" y la interfaz oper-status
física está "inactiva", la status
variable contiene el texto p-down
. ../
( selecciona la interfaz física.)
69 <xsl:when test="oper-status='down' and ../oper-status='down'"> 70 <xsl:text>p-down</xsl:text> 71 </xsl:when>
Las líneas 72 a 74 especifican que si oper-status
está 'abajo', la status
variable contiene el texto down
.
72 <xsl:when test="oper-status='down'"> 73 <xsl:text>down</xsl:text> 74 </xsl:when>
Las líneas 75 a 77 especifican que si ninguno de los casos de prueba es verdadero, la status
variable contiene oper-status
y admin-status
concatena con una barra diagonal como separador.
75 <xsl:otherwise> 76 <xsl:value-of select="concat(oper-status, '/', admin-status)"/> 77 </xsl:otherwise>
Las líneas 78 y 79 son etiquetas de cierre.
78 </xsl:choose> 79 </xsl:variable>
Las líneas 80 a 89 definen una variable denominada desc
. Una <xsl:choose>
instrucción rellena la variable seleccionando la descripción de interfaz más específica disponible. Si se incluye una descripción de interfaz lógica en la configuración, se utiliza para rellenar la desc
variable. Si no es así, se utiliza la descripción de la interfaz física. Si no se incluye ninguna descripción de interfaz física en la configuración, la variable permanece vacía. Como siempre en XSLT, se ejecuta la primera <xsl:when>
instrucción que se evalúa como TRUE y el resto se ignora.
80 <xsl:variable name="desc"> 81 <xsl:choose> 82 <xsl:when test="description"> 83 <xsl:value-of select="description"/> 84 </xsl:when> 85 <xsl:when test="../description"> 86 <xsl:value-of select="../description"/> 87 </xsl:when> 88 </xsl:choose> 89 </xsl:variable>
El resto del script especifica cómo se muestra la salida del modo operativo.
Las líneas 90 y 91 especifican que el nombre de la interfaz lógica se muestra primero en la salida.
90 <logical-interface> 91 <name><xsl:value-of select="name"/></name>
Las líneas 92 a 94 prueban si la desc
variable tiene un número de caracteres distinto de cero. Si el número de caracteres es mayor que cero, la descripción de la interfaz se muestra en la ubicación estándar del admin-status
campo. (En la salida estándar, el admin-status
campo se muestra en la segunda línea).
92 <xsl:if test="string-length($desc)"> 93 <admin-status><xsl:value-of select="$desc"/></admin-status> 94 </xsl:if>
La línea 95 especifica que el estado de la interfaz definido en la status
variable se muestra a continuación.
95 <admin-status><xsl:value-of select="$status"/></admin-status>
Las líneas 96 a 103 especifican que si incluye el argumento al ejecutar el protocol
script, sólo se mostrarán las interfaces con ese protocolo configurado. Si no incluye el protocol
argumento, se muestran todas las interfaces.
96 <xsl:choose> 97 <xsl:when test="$protocol"> 98 <xsl:copy-of select="address-family[address-family-name = $protocol]"/> 99 </xsl:when> 100 <xsl:otherwise> 101 <xsl:copy-of select="address-family"/> 102 </xsl:otherwise> 103 </xsl:choose>
Las líneas 104 a 106 son etiquetas de cierre.
104 </logical-interface> 105 </xsl:template> 106 </xsl:stylesheet>
Sintaxis de SLAX
La versión SLAX del script es la siguiente:
version 1.0; ns junos = "http://xml.juniper.net/junos/*/junos"; ns xnm = "http://xml.juniper.net/xnm/1.1/xnm"; ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0"; import "../import/junos.xsl"; var $arguments = { <argument> { <name> "interface"; <description> "Name of interface to display"; } <argument> { <name> "protocol"; <description> "Protocol to display (inet, inet6)"; } } param $interface; param $protocol; match / { <op-script-results> { var $rpc = { <get-interface-information> { <terse>; if ($interface) { <interface-name> $interface; } } } var $out = jcs:invoke($rpc); <interface-information junos:style="terse"> { if ($protocol='inet' or $protocol='inet6' or $protocol='mpls' or $protocol='tnp') { for-each ($out/physical-interface/ logical-interface[address-family/address-family-name = $protocol]) { call intf(); } } else if ($protocol) { <xnm:error> { <message> { expr "invalid protocol: "; expr $protocol; } } } else { for-each ($out/physical-interface/logical-interface) { call intf(); } } } } } intf () { var $status = { if (admin-status='up' and oper-status='up') { } else if (admin-status='down') { expr "offline"; } else if (oper-status='down' and ../admin-status='down') { expr "p-offline"; } else if (oper-status='down' and ../oper-status='down') { expr "p-down"; } else if (oper-status='down') { expr "down"; } else { expr oper-status _ '/' _ admin-status; } } var $desc = { if (description) { expr description; } else if (../description) { expr ../description; } } <logical-interface> { <name> name; if (string-length($desc)) { <admin-status> $desc; } <admin-status> $status; if ($protocol) { copy-of address-family[address-family-name = $protocol]; } else { copy-of address-family; } } }
Configuración
Procedimiento
Procedimiento paso a paso
Para descargar, habilitar y probar el script:
Copie el script XSLT o SLAX en un archivo de texto, asigne al archivo el nombre interface.xsl o interface.slax según corresponda y cópielo en el directorio / var/db/scripts/op/ del dispositivo.
En el modo de configuración, incluya la
file
instrucción en el nivel jerárquico[edit system scripts op]
e interface.xsl o interface.slax , según corresponda.[edit system scripts op] user@host# set file interface.(slax | xsl)
Emita el
commit and-quit
comando para confirmar la configuración y volver al modo operativo.[edit] user@host# commit and-quit
Ejecute el script op emitiendo el comando de
op interface
modo operativo.
Verificación
Comprobación de la salida del script de confirmación
Propósito
Compruebe que el script se comporta como se esperaba.
Acción
Emita los comandos operativos y op interface
compare los show interfaces terse
resultados. El show interfaces terse
comando muestra el resultado estándar. El op interface
comando muestra la salida personalizada.
user@host> show interfaces terse Interface Admin Link Proto Local Remote dsc up up fxp0 up up fxp0.0 up up inet 192.168.71.246/21 fxp1 up up fxp1.0 up up inet 10.0.0.4/8 inet6 fe80::200:ff:fe00:4/64 fc00::10:0:0:4/64 tnp 4 gre up up ipip up up lo0 up up lo0.0 up up inet 127.0.0.1 --> 0/0 lo0.16385 up up inet inet6 fe80::2a0:a5ff:fe12:2f04 lsi up up mtun up up pimd up up pime up up tap up up user@host> op interface Interface Admin Link Proto Local Remote fxp0.0 This is the Ethernet Management interface. inet 192.168.71.246/21 fxp1.0 inet 10.0.0.4/8 inet6 fe80::200:ff:fe00:4/64 fc00::10:0:0:4/64 tnp 4 lo0.0 inet 127.0.0.1 --> 0/0 lo0.16385 inet inet6 fe80::2a0:a5ff:fe12:2f04-->
Emita el comando operativo para diferentes niveles de jerarquía y revise el op interface
resultado. Por ejemplo:
user@host> op interface interface fxp0 Interface Admin Link Proto Local Remote fxp0.0 This is the Ethernet Management interface. inet 192.168.71.246/21 user@host> op interface protocol inet Interface Admin Link Proto Local Remote fxp0.0 This is the Ethernet Management interface. inet 192.168.71.246/21 fxp1.0 inet 10.0.0.4/8 lo0.0 inet 127.0.0.1 --> 0/0 lo0.16385 inet