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, , detaily 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, , , mplso tnp, inet6la 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 , , mplso tnp, inet6se genera un mensaje de ineterror.
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
fileinstrucció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-quitcomando 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 interfacemodo 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