Ayúdenos a mejorar su experiencia.

Háganos saber su opinión.

¿Podría dedicar dos minutos de su tiempo a completar una encuesta?

close
keyboard_arrow_left
list Table of Contents

¿Fue útil esta traducción automática?

starstarstarstarstar
Go to English page
DESCARGO DE RESPONSABILIDAD:

Esta página será traducida por software de traducción automática de terceros. Si bien nos hemos esforzado por proporcionar una traducción de calidad, Juniper Networks no puede garantizar su corrección. En caso de duda respecto a la exactitud de la información que ofrece esta traducción, consulte la versión en inglés. El PDF descargable está disponible solo en inglés.

Ejemplo: Usar una RPC yang personalizada para recuperar información operativa en dispositivos Junos

date_range 08-Sep-22

Puede agregar modelos de datos YANG que definan RPCs personalizadas en dispositivos Junos. La creación de RPCs personalizados le permite definir con precisión los parámetros de entrada y las operaciones, así como los campos de salida y el formato para sus tareas operativas específicas en esos dispositivos. En este ejemplo, se presenta un script de acción y UNA RPC personalizados que recuperan información operativa del dispositivo y muestran la salida de CLI personalizada.

El RPC se agrega al esquema de Junos OS en el dispositivo. Cuando se ejecuta el RPC en la CLI, imprime el nombre y el estado operativo de las interfaces físicas solicitadas.

Requisitos

En este ejemplo, se utilizan los siguientes componentes de hardware y software:

  • Dispositivo que ejecuta la versión 17.3R1 o posterior de Junos OS que admite la carga de modelos de datos YANG personalizados.

Descripción general de la RPC y el script de acción

El módulo YANG de este ejemplo define una RPC personalizada para devolver el nombre y el estado operativo de ciertas interfaces físicas. El módulo rpc-interface-status YANG se guarda en el archivo rpc-interface-status.yang . El módulo importa los módulos de extensión de Junos OS, que proporcionan las extensiones necesarias para ejecutar RPCs personalizadas en el dispositivo y personalizar la salida de CLI.

El módulo define la get-interface-status RPC. La <get-interface-status> etiqueta de solicitud se utiliza para ejecutar de forma remota la RPC en el dispositivo. En la definición de RPC, la junos:command instrucción define el comando que se utiliza para ejecutar la RPC en la CLI, que en este caso es show intf status.

Las junos:action-execute instrucciones and junos:script definen la secuencia de comandos de acción que se invoca cuando se ejecuta el RPC. En este ejemplo, se utiliza una secuencia de comandos de acción de Python denominada rpc-interface-status.py para recuperar la información requerida por la RPC y devolver los elementos de salida XML tal como se definen en la instrucción RPC output .

content_copy zoom_out_map
  rpc get-interface-status {
     description "RPC example to retrieve interface status";

     junos:command "show intf status" {
        junos:action-execute {
          junos:script "rpc-interface-status.py";
        }
     }
    ...
Nota:

A partir de Junos OS versión 17.3, la action-execute instrucción es una subestación a command. En versiones anteriores, las action-execute instrucciones y command se colocan en el mismo nivel, y la command instrucción es opcional.

El RPC tiene un parámetro de entrada denominado match, que determina las interfaces que se deben incluir en la salida. Cuando se ejecuta el RPC, se incluye una cadena que coincide en las interfaces deseadas, por ejemplo, ge-0*. Una cadena vacía ("") coincide con todas las interfaces. La secuencia de comandos de acción define el valor predeterminado como una cadena vacía, de match modo que si el usuario omite este argumento, la salida incluirá información para todas las interfaces.

content_copy zoom_out_map
     input {
       leaf match {
         description "Requested interface match condition";
         type string;
       }
     }

El RPC también define los nodos de salida que debe emitir la secuencia de comandos de acción correspondiente. El nodo raíz es el <interface-status-info> elemento, que contiene cero o más <status-info> elementos que encierran los <interface> nodos y <status> para una interfaz coincidente. La junos-odl:format interface-status-info-format instrucción define el formato para el resultado que se muestra en la CLI. Este nodo no se emite en el árbol XML de salida.

content_copy zoom_out_map
     output {
       container interface-status-info {
         list status-info {
           leaf interface {
             type string;
             description "Physical inteface name";
           }
           leaf status {
             type string;
             description "Operational status";
           }
           junos-odl:format interface-status-info-format {
             ...
           }
         }
       }
     }

En este ejemplo, se presentan dos versiones de la secuencia de comandos de acción de Python. Los scripts muestran diferentes medios para recuperar la salida del comando operativo, pero ambos scripts emiten una salida RPC idéntica. La primera secuencia de comandos de acción usa el módulo Python subprocess para ejecutar el show interfaces match-value | display xml comando y, luego, convierte la salida de cadena en XML. La segunda secuencia de comandos de acción usa Junos PyEZ para ejecutar el equivalente DE RPC del show interfaces match-value comando. Ambos scripts usan código idéntico para analizar la salida del comando y extraer el nombre y el estado operativo de cada interfaz física. Los scripts construyen el XML para la salida DE LA RPC y, a continuación, imprimen la salida, lo que devuelve la información al dispositivo. El árbol XML debe coincidir exactamente con la jerarquía definida en la RPC.

Nota:

Los dispositivos Junos definen espacios de nombres dependientes de versiones para muchos de los elementos de la salida operativa, incluido el <interface-information> elemento. Para hacer que la versión junos OS de RPC sea independiente, el código usa la local-name() función en las expresiones de XPath para estos elementos. Puede elegir incluir la asignación del espacio de nombres como un argumento para xpath() y calificar los elementos con el espacio de nombres adecuado.

El módulo que contiene el RPC y el archivo de secuencia de comandos de acción se agregan al dispositivo como parte de un nuevo paquete YANG denominado intf-rpc.

Módulo YANG

Módulo YANG

El módulo YANG, rpc-interface-status.yang, define el RPC, el comando utilizado para ejecutar el RPC en la CLI y el nombre de la secuencia de comandos de acción que se invocará cuando se ejecuta la RPC. El nombre base del archivo debe coincidir con el nombre del módulo.

content_copy zoom_out_map
/*
* Copyright (c) 2014 Juniper Networks, Inc.
* All rights reserved.
*/

module rpc-interface-status {
  namespace "http://yang.juniper.net/examples/rpc-cli";
  prefix rpc-cli;

  import junos-extension-odl {
    prefix junos-odl;
  }
  import junos-extension {
    prefix junos;
  }

  organization
    "Juniper Networks, Inc.";

  description
    "Junos OS YANG module for RPC example";

  rpc get-interface-status {
     description "RPC example to retrieve interface status";

     junos:command "show intf status" {
        junos:action-execute {
          junos:script "rpc-interface-status.py";
        }
     }

     input {
       leaf match {
         description "Requested interface match condition";
         type string;
       }
     }
     output {
       container interface-status-info {
         list status-info {
           leaf interface {
             type string;
             description "Physical interface name";
           }
           leaf status {
             type string;
             description "Operational status";
           }
           junos-odl:format interface-status-info-format {
             junos-odl:header "Physical Interface - Status\n";
             junos-odl:indent 5;
             junos-odl:comma;
             junos-odl:space;
             junos-odl:line {
               junos-odl:field "interface";
               junos-odl:field "status";
             }
           }
         }
       }
     }
  }
}

Script de acción

La secuencia de comandos de acción correspondiente es rpc-interface-status.py. En este ejemplo, se presentan dos scripts de acción que utilizan medios diferentes para recuperar los datos. Un script usa el módulo Python subprocess y el otro script usa la biblioteca Junos PyEZ. Ambos scripts emiten la misma salida XML de RPC.

Nota:

A partir de Junos OS versión 21.2R1 y Junos OS Evolved versión 21.2R1, cuando el dispositivo pasa argumentos de línea de comandos a una secuencia de comandos de Python, prefija un guión único (-) a nombres de argumentos de un solo carácter y prefijo dos guiones (--) a nombres de argumentos de varios caracteres.

Secuencia de comandos de acción (uso subprocess)

La siguiente secuencia de comandos de acción usa el módulo Python subprocess para ejecutar el comando operativo y recuperar los datos. En este ejemplo, se proporcionan dos versiones de la secuencia de comandos, que manejan adecuadamente los argumentos de línea de comandos de la secuencia de comandos para las diferentes versiones.

Junos OS versión 21.1 y anteriores

content_copy zoom_out_map
#!/usr/bin/python
# Junos OS Release 21.1 and earlier

import sys
import subprocess
from lxml import etree

def get_device_info(cmd):
    """
    Execute Junos OS operational command and parse output
    :param: str cmd: operational command to execute
    :returns: List containing the XML data for each interface
    """

    # execute Junos OS operational command and retrieve output
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    tmp = proc.stdout.read()
    root = etree.fromstring(tmp.strip())

    xml_items = []

    # parse output for required data
    for intf in root.xpath("/rpc-reply \
        /*[local-name()='interface-information'] \
        /*[local-name()='physical-interface']"):

        # retrieve data for the interface name and operational status
        name = intf.xpath("*[local-name()='name']")[0].text
        oper_status = intf.xpath("*[local-name()='oper-status']")[0].text

        # append the XML for each interface to a list
        xml_item = etree.Element('status-info')
        interface = etree.SubElement(xml_item, 'interface')
        interface.text = name
        status = etree.SubElement(xml_item, 'status')
        status.text = oper_status
        xml_items.append(xml_item)

    return xml_items


def generate_xml(cmd):
    """
    Generate the XML tree for the RPC output
    :param: str cmd: operational command from which to retrieve data
    :returns: XML tree for the RPC output
    """

    xml = etree.Element('interface-status-info')

    intf_list_xml = get_device_info(cmd)
    for intf in intf_list_xml:
        xml.append(intf)
    return xml


def main():

    args = {'match': ""}
    for arg in args.keys():
        if arg in sys.argv:
            index = sys.argv.index(arg)
            args[arg] = sys.argv[index+1]

    # define the operational command from which to retrieve information
    cli_command = 'show interfaces ' + args['match'] + ' | display xml'
    cmd = ['cli', '-c', cli_command]

    # generate the XML for the RPC output
    rpc_output_xml = generate_xml(cmd)

    # print RPC output
    print (etree.tostring(rpc_output_xml, pretty_print=True, encoding='unicode'))


if __name__ == '__main__':

    main()

Junos OS versión 21.2R1 y posteriores

content_copy zoom_out_map
#!/usr/bin/python3
# Junos OS Release 21.2R1 and later

import subprocess
import argparse
from lxml import etree

def get_device_info(cmd):
    """
    Execute Junos OS operational command and parse output
    :param: str cmd: operational command to execute
    :returns: List containing the XML data for each interface
    """

    # execute Junos OS operational command and retrieve output
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    tmp = proc.stdout.read()
    root = etree.fromstring(tmp.strip())

    xml_items = []

    # parse output for required data
    for intf in root.xpath("/rpc-reply \
        /*[local-name()='interface-information'] \
        /*[local-name()='physical-interface']"):

        # retrieve data for the interface name and operational status
        name = intf.xpath("*[local-name()='name']")[0].text
        oper_status = intf.xpath("*[local-name()='oper-status']")[0].text

        # append the XML for each interface to a list
        xml_item = etree.Element('status-info')
        interface = etree.SubElement(xml_item, 'interface')
        interface.text = name
        status = etree.SubElement(xml_item, 'status')
        status.text = oper_status
        xml_items.append(xml_item)

    return xml_items


def generate_xml(cmd):
    """
    Generate the XML tree for the RPC output
    :param: str cmd: operational command from which to retrieve data
    :returns: XML tree for the RPC output
    """

    xml = etree.Element('interface-status-info')

    intf_list_xml = get_device_info(cmd)
    for intf in intf_list_xml:
        xml.append(intf)
    return xml


def main():

    parser = argparse.ArgumentParser(description='This is a demo script.')
    parser.add_argument('--match', required=False, default='')
    parser.add_argument('--rpc_name', required=True)
    args = parser.parse_args()

    # define the operational command from which to retrieve information
    cli_command = 'show interfaces ' + args.match + ' | display xml'
    cmd = ['cli', '-c', cli_command]

    # generate the XML for the RPC output
    rpc_output_xml = generate_xml(cmd)

    # print RPC output
    print (etree.tostring(rpc_output_xml, pretty_print=True, encoding='unicode'))


if __name__ == '__main__':

    main()

Secuencia de comandos de acción (uso de Junos PyEZ)

La siguiente secuencia de comandos de acción usa Junos PyEZ para ejecutar el comando operativo y recuperar los datos. En este ejemplo, se proporcionan dos versiones de la secuencia de comandos, que manejan adecuadamente los argumentos de línea de comandos de la secuencia de comandos para las diferentes versiones.

Junos OS versión 21.1 y anteriores

content_copy zoom_out_map
#!/usr/bin/python
# Junos OS Release 21.1 and earlier

import sys
from jnpr.junos import Device
from jnpr.junos.exception import *
from lxml import etree

def get_device_info(match):
    """
    Execute Junos OS operational command and parse output
    :param: str match: interface match condition
    :returns: List containing the XML data for each interface
    """

    # execute Junos OS operational command and retrieve output
    try:
        with Device() as dev:
            if (match == ""):
                root = dev.rpc.get_interface_information( )
            else:
                root = dev.rpc.get_interface_information(interface_name=match)
    except Exception:                
        sys.exit()

    xml_items = []

    # parse output for required data
    for intf in root.xpath("/rpc-reply \
        /*[local-name()='interface-information'] \
        /*[local-name()='physical-interface']"):

        # retrieve data for the interface name and operational status
        name = intf.xpath("*[local-name()='name']")[0].text
        oper_status = intf.xpath("*[local-name()='oper-status']")[0].text

        # append the XML for each interface to a list
        xml_item = etree.Element('status-info')
        interface = etree.SubElement(xml_item, 'interface')
        interface.text = name
        status = etree.SubElement(xml_item, 'status')
        status.text = oper_status
        xml_items.append(xml_item)

    return xml_items


def generate_xml(match):
    """
    Generate the XML tree for the RPC output
    :param: str match: interface match condition
    :returns: XML tree for the RPC output
    """

    xml = etree.Element('interface-status-info')

    intf_list_xml = get_device_info(match)
    for intf in intf_list_xml:
        xml.append(intf)
    return xml


def main():

    args = {'match': ""}

    for arg in args.keys():
        if arg in sys.argv:
            index = sys.argv.index(arg)
            args[arg] = sys.argv[index+1]

    # generate the XML for the RPC output
    rpc_output_xml = generate_xml(args['match'])

    # print RPC output
    print (etree.tostring(rpc_output_xml, pretty_print=True, encoding='unicode'))

if __name__ == '__main__':

    main()

Junos OS versión 21.2R1 y posteriores

content_copy zoom_out_map
#!/usr/bin/python3
# Junos OS Release 21.2R1 and later

import sys
import argparse
from jnpr.junos import Device
from jnpr.junos.exception import *
from lxml import etree

def get_device_info(match):
    """
    Execute Junos OS operational command and parse output
    :param: str match: interface match condition
    :returns: List containing the XML data for each interface
    """

    # execute Junos OS operational command and retrieve output
    try:
        with Device() as dev:
            if (match == ""):
                root = dev.rpc.get_interface_information( )
            else:
                root = dev.rpc.get_interface_information(interface_name=match)
    except Exception:                
        sys.exit()

    xml_items = []

    # parse output for required data
    for intf in root.xpath("/rpc-reply \
        /*[local-name()='interface-information'] \
        /*[local-name()='physical-interface']"):

        # retrieve data for the interface name and operational status
        name = intf.xpath("*[local-name()='name']")[0].text
        oper_status = intf.xpath("*[local-name()='oper-status']")[0].text

        # append the XML for each interface to a list
        xml_item = etree.Element('status-info')
        interface = etree.SubElement(xml_item, 'interface')
        interface.text = name
        status = etree.SubElement(xml_item, 'status')
        status.text = oper_status
        xml_items.append(xml_item)

    return xml_items


def generate_xml(match):
    """
    Generate the XML tree for the RPC output
    :param: str match: interface match condition
    :returns: XML tree for the RPC output
    """

    xml = etree.Element('interface-status-info')

    intf_list_xml = get_device_info(match)
    for intf in intf_list_xml:
        xml.append(intf)
    return xml


def main():

    parser = argparse.ArgumentParser(description='This is a demo script.')
    parser.add_argument('--match', required=False, default='')
    parser.add_argument('--rpc_name', required=True)
    args = parser.parse_args()

    # generate the XML for the RPC output
    rpc_output_xml = generate_xml(args.match)

    # print RPC output
    print (etree.tostring(rpc_output_xml, pretty_print=True, encoding='unicode'))

if __name__ == '__main__':

    main()

Habilitación de la ejecución de scripts de Python

Para permitir que el dispositivo ejecute scripts de Python sin firmar:

  1. Configure la language python instrucción orlanguage python3, según corresponda para la versión de Junos OS.
    content_copy zoom_out_map
    [edit]
    user@host# set system scripts language (python | python3)
    
    Nota:

    A partir de Junos OS versión 20.2R1 y Junos OS Evolved versión 22.3R1, el dispositivo usa Python 3 para ejecutar scripts de acción y traducción yang. En versiones anteriores, Junos OS solo usa Python 2.7 para ejecutar estos scripts, y Junos OS Evolved usa Python 2.7 de forma predeterminada para ejecutar los scripts.

  2. Confirme la configuración.
    content_copy zoom_out_map
    [edit]
    user@host# commit and-quit
    

Cargar el RPC en el dispositivo

Para agregar el CÓDIGO DE ACCIÓN y EL RPC al esquema de Junos:

  1. Descargue el módulo YANG y la secuencia de comandos de acción al dispositivo Junos.
  2. Asegúrese de que la secuencia de comandos de acción de Python cumple con los siguientes requisitos:
    • El propietario del archivo es raíz o un usuario de la clase de inicio de sesión de Junos OS super-user .

    • Solo el propietario del archivo tiene permiso de escritura para el archivo.

    • La secuencia de comandos incluye la línea de directiva de intérprete adecuada, tal como se describe en Create Action Scripts for YANG RPCs en dispositivos Junos.

  3. (Opcional) Valide la sintaxis para el módulo YANG y la secuencia de comandos de acción.
    content_copy zoom_out_map
    user@host> request system yang validate module /var/tmp/rpc-interface-status.yang action-script /var/tmp/rpc-interface-status.py
    YANG modules validation : START
    YANG modules validation : SUCCESS
    Scripts syntax validation : START
    Scripts syntax validation : SUCCESS
    
  4. Agregue el módulo YANG y la secuencia de comandos de acción a un nuevo paquete YANG.
    content_copy zoom_out_map
    user@host> request system yang add package intf-rpc module /var/tmp/rpc-interface-status.yang action-script /var/tmp/rpc-interface-status.py
    YANG modules validation : START
    YANG modules validation : SUCCESS
    Scripts syntax validation : START
    Scripts syntax validation : SUCCESS
    TLV generation: START
    TLV generation: SUCCESS
    Building schema and reloading /config/juniper.conf.gz ...
    Restarting mgd ...
    
    
    Nota:

    A partir de Junos OS versión 17.3R1, cuando carga modelos de datos yang personalizados en el dispositivo, no es necesario cargar explícitamente ningún módulo de extensión de Junos OS necesario. En versiones anteriores, debe cargar los módulos de extensión de Junos OS para cualquier paquete que use los módulos.

  5. Cuando el sistema le pida que reinicie la CLI de Junos OS, presione Enter para aceptar el valor predeterminado de yes, o tipo yes y presione Enter.
    content_copy zoom_out_map
    WARNING: cli has been replaced by an updated version:
    ...
    Restart cli using the new version ? [yes,no] (yes) yes
    
    Restarting cli ...
    

Verificación de la RPC

Propósito

Compruebe que el RPC funciona como se esperaba.

Acción

Desde el modo operativo, ejecute el RPC en la CLI mediante la emisión del comando definido por la junos:command instrucción en la definición de RPC e incluya el argumento de match entrada. En este ejemplo, el argumento match se usa para coincidir en todas las interfaces que comienzan con ge-0.

content_copy zoom_out_map
user@host> show intf status match ge-0*
Physical Interface - Status
     ge-0/0/0, up
     ge-0/0/1, up
     ge-0/0/2, up
     ge-0/0/3, up
     ge-0/0/4, up
     ge-0/0/5, up
     ge-0/0/6, up
     ge-0/0/7, up
     ge-0/0/8, up
     ge-0/0/9, up
     ge-0/1/0, up
     ge-0/1/1, up
     ge-0/1/2, up
     ge-0/1/3, up
     ge-0/1/4, up
     ge-0/1/5, up
     ge-0/1/6, up
     ge-0/1/7, up
     ge-0/1/8, up
     ge-0/1/9, up

También puede ajustar la condición de coincidencia para devolver diferentes conjuntos de interfaces. Por ejemplo:

content_copy zoom_out_map
user@host> show intf status match *e-0/*/0
Physical Interface - Status
     ge-0/0/0, up
     pfe-0/0/0, up
     ge-0/1/0, up
     xe-0/2/0, up
     xe-0/3/0, up

Para devolver el mismo resultado en formato XML, anexe el | display xml filtro al comando.

content_copy zoom_out_map
user@host> show intf status match *e-0/*/0 | display xml
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/17.3R1/junos">
    <interface-status-info>
          <status-info>
            <interface>ge-0/0/0</interface>
            <status>up</status>
          </status-info>
          <status-info>
            <interface>pfe-0/0/0</interface>
            <status>up</status>
          </status-info>
          <status-info>
            <interface>ge-0/1/0</interface>
            <status>up</status>
          </status-info>
          <status-info>
            <interface>xe-0/2/0</interface>
            <status>up</status>
          </status-info>
          <status-info>
            <interface>xe-0/3/0</interface>
            <status>up</status>
          </status-info>
    </interface-status-info>
    <cli>
        <banner></banner>
    </cli>
</rpc-reply>
Nota:

Para que coincida con todas las interfaces, omita el match argumento o establezca el valor del argumento en una cadena vacía ("").

Significado

Cuando ejecuta el RPC, el dispositivo invoca la secuencia de comandos de acción. La secuencia de comandos de acción ejecuta el comando operativo para recuperar la información de la interfaz del dispositivo, analiza la salida de la información deseada e imprime la jerarquía XML para la salida de RPC tal como se define en la instrucción RPC output . Cuando se ejecuta el RPC en la CLI, el dispositivo usa el formato de CLI definido en la RPC para convertir la salida XML en la salida de CLI mostrada. Para devolver la salida XML original, anexe el | display xml filtro al comando.

Nota:

Cuando el RPC se ejecuta de forma remota mediante la etiqueta de solicitud DE RPC, el formato predeterminado de la salida es XML.

Solución de problemas de errores de ejecución de RPC

Problema

Descripción

Cuando ejecuta la RPC, el dispositivo genera el siguiente error:

content_copy zoom_out_map
error: open failed: /var/db/scripts/action/rpc-interface-status.py: Permission denied

Causa

El usuario que invocó la RPC no tiene los permisos necesarios para ejecutar la secuencia de comandos de acción de Python correspondiente.

Solución

Los usuarios solo pueden ejecutar scripts de Python sin firmar en dispositivos Junos cuando los permisos de archivo de la secuencia de comandos incluyen permiso de lectura para la primera clase en la que el usuario se encuentra, en el orden de usuario, grupo u otros.

Compruebe si la secuencia de comandos tiene los permisos necesarios para que ese usuario ejecute la secuencia de comandos y ajuste los permisos, si corresponde. Si actualiza los permisos, también debe actualizar el paquete YANG para que este cambio tenga efecto. Por ejemplo:

content_copy zoom_out_map
admin@host> file list ~ detail
-rw-------  1 admin    wheel  2215 Apr 20 11:36 rpc-interface-status.py
content_copy zoom_out_map
admin@host> file change-permission rpc-interface-status.py permission 644
admin@host> file list ~ detail
-rw-r--r--  1 admin    wheel  2215 Apr 20 11:36 rpc-interface-status.py
content_copy zoom_out_map
admin@host> request system yang update intf-rpc action-script /var/tmp/rpc-interface-status.py
Scripts syntax validation : START
Scripts syntax validation : SUCCESS
Tabla de historial de versiones
Lanzamiento
Descripción
21.2R1 y 21.2R1-EVO
A partir de Junos OS versión 21.2R1 y Junos OS Evolved versión 21.2R1, cuando el dispositivo pasa argumentos de línea de comandos a una secuencia de comandos de Python, prefija un guión único (-) a nombres de argumentos de un solo carácter y prefijo dos guiones (--) a nombres de argumentos de varios caracteres.
external-footer-nav