Tablas y vistas con Junos Pyez

(Nayan Gadre) (12 de septiembre de 2020)

Estas son notas creadas mientras trabajando con la biblioteca Junos pyez para la automatización de redes. Junos proporciona tablas y vistas para establecer y extraer datos de configuración personalizados. Todo el código pyez y ncclient es de código abierto bajo la licencia Apache 2.0

Usted define una tabla y una vista en un archivo Yaml en lib / jnpr / junos / recursos
como “ user.yml ” y su correspondiente archivo de cargador como “ user.py

user.yml
user.py

El» user.py ”se usa para convertir las definiciones de tabla y vista del archivo yaml en elementos del diccionario global de Python. Aquí \_\_file \_\_ apunta al « user.py ” archivo que lo hará. luego se convierte en el nombre de archivo “ user.yml ”. El loadyaml de junos pyez convertirá el “ user.yml ”en un diccionario para agregarlo al diccionario globals () .

Tanto las definiciones de tabla como de vista en el yaml se convierten en clases en python. loadyaml es un método de fábrica y se expone como API pública mediante \_\_ all \_\_ declaración pitónica. Proporciona un diccionario de definiciones de nombre de elemento y de clase de elemento como se puede ver en una línea.

El archivo user.yml está dividido en 2 claves de nivel superior: “ UserTable ” y “ UserView ” por lo que loadyaml devolverá 2 clases con estos nombres.

diccionario convertido del user.yml

Este diccionario se pasa al FactoryLoader.load ( ) método para generar clases:

FactoryLoader (). load (yaml.load (open (ruta, «r»), Loader = yaml.FullLoader))

El propósito de la clase Factory Loader

El método items () del diccionario r devuelve un objeto de vista que contiene una lista de tuplas que contienen pares clave-valor.

La forma en que el cargador de fábrica decide si la tabla proporcionada y el esquema de vista son para configuración o para operaciones es a través de las claves presentes en el esquema . Por ejemplo: “ set ” y “ get ” las claves la convertirían en una tabla de configuración,
rpc ” entonces es una operación tabla, “ comando ” o “ título » entonces es una tabla de comandos, también hay una combinación confusa de « item ” “ view ”y“ * ”que también dicta si es una tabla de comandos.

Ya que nos estamos enfocando en el « user.yml ” podemos ver que es «una tabla de configuración, ya que tiene un» establecer ” en su jerarquía. Por lo tanto, rellenaremos el \_item\_cfgtables con UserTable clave.

Esta es la función del constructor de clases para generar la clase de tabla para tablas de tipo de configuración.

La clase Table contiene una referencia a la clase View, por lo tanto si hay una vista definida en la sección de tabla, crearemos una clase para esa vista usando el método \_build\_view () y configuraremos la clase como el valor de la clave “ view ”.

El método get () del diccionario, permite establecer un valor predeterminado si la clave no está presente , aquí la clave « view\_name ” estará ausente, por lo que la \_build\_view ( view\_name ) creará una clase y asociará la clase como valor a view\_name clave. También extraerá los grupos, eval, campos y los almacenará en los campos internos de los objetos de vista.

Primero comprobaremos cómo funciona el contenedor CFGTABLE se crea en \_CFGTBL
\_CFGTBL = FactoryCfgTable

Python le permite para crear clases o tipos dinámicos usando el método “ type ”.
Si “ type ”se pasa un objeto existente, devuelve su tipo. Sin embargo, si « tipo ” se pasan 3 argumentos, « nombre de clase ”,“ tupla de bases ”,“ dict ”luego devuelve una nueva clase. También hay un método “ vars ”, que devuelve \_\_dict\_\_ atributo, que almacena atributos de escritura de los objetos. Python crea otras clases usando metaclases.

Podemos pasar el nombre de la clase de la cual nuestra nueva clase heredará como una sola tupla: Por ejemplo: new\_cls = type (table\_name, (CfgTable,), {})

Si “ set ”la palabra clave está presente en la sección Tabla:
por ejemplo: set: system / login / user
Por lo tanto, también deberíamos pasar la clase base de configuración para crear nuestra clase UserTable:
Por ejemplo: new\_cls = type (table\_name, (CfgTable, Config), {})

campos que se completan automáticamente en la clase

Una vez que la clase se crea, lo agregaremos al catálogo de clases de factoryLoader: self.catalog [table\_name] = cls

Ahora vamos a construir la clase de vista:

view\_name = tbl\_dict [“ view ”]
tbl\_dict [“ view ”] = self.catalog.get (view\_name, self.\_build\_view (view\_name))

El view\_name definido en el archivo “ user.yml ” es “ userView ”.

Finalmente,“ cargar ”Devolverá un catálogo de clases creado por la clase FactoryLoader .

Entonces, resumiendo la ruta:

Eso solo completa una parte donde el yml se convierte en Clases que luego se pueden usar para operar. Entonces, a continuación, comenzamos creando un objeto de nuestra clase UserTable.

user\_table = UserTable (dev)

Desde el recién creado UserTable hereda de CfgTable y las clases base de configuración, heredaremos el constructor y todos los métodos definidos en esas clases base. Tan pronto como creamos un nuevo objeto UserTable , llama al objeto \_\_init\_\_ de las clases principales. Dado que “ set ” se menciona en el archivo yml, también llamaremos al constructor de config clase base.

Después de esto, llame el método get () para obtener los datos de configuración del sistema / inicio de sesión / usuario jerarquía.
Primero verificaremos la opción namesonly = false .

Recuerde que la jerarquía para la expresión xpath ya se estableció a través de set: system / login / user declaración“ user.yml ”. Una función \_build\_xml traduce eso en un. XML como el siguiente:

Si el usuario especificó un nombre de usuario específico, denominado « namekey ”, entonces necesitamos para insertar eso en el xml generado anteriormente. Por ejemplo: get (user = ”regress”) insertaría el elemento de nombre con el valor regresión:

regress

todo se empaqueta en get\_cmd y se envía a self.RPC.get\_config (get\_cmd)
Un XML típico- RPC tiene el siguiente aspecto:

formato de XML de llamada al método RPC XML

Nuestro XML para obtener información del usuario se ve así:

Este XML-RPC se convierte en una solicitud HTTP POST y se envía al servidor: ejecuta un XML RPC y devuelve los resultados como XML o Python nativo

La llamada rpc real se realiza mediante el método rpc de ncclient sobre ssh para que los datos estén encriptados.

El manejo de RPC de el rpc\_cmd\_e es. hecho por ncclient que proporciona implementación para netconf sobre ssh. Será difícil entender dónde está realmente definido el método rpc en el objeto Manager () del paquete ncclient. Después de estudiar la biblioteca ncclient, descubrí que se define como un diccionario de métodos con «rpc» = ExecuteRpc , y este diccionario es específico del proveedor. Haga clic aquí para leer más .

Esta operación completa para nombrar el diccionario se crea para cada solicitud de conexión basada en el proveedor y se devuelve.

El RPC XML final enviado a través del servidor ssh también netconf en el dispositivo Junos

Un rápido resumen del inicio y el intercambio de la sesión netconf:

El cliente debe iniciar una conexión netconf al puerto 830 sobre ssh. El servidor debe enviar su mensaje HOLA inmediatamente, y el cliente también debe hacer lo mismo. Todo el mensaje hello > especifica las capacidades del cliente y del servidor. Luego, el servidor debe esperar para procesar cualquier solicitud rpc > y debe enviar un rpc-reply >. El cliente puede agregar tantos atributos XML al elemento rpc > como desee, y el el servidor devolverá todos esos atributos en el elemento rpc-reply >.

La respuesta se analiza, para ok > y rpc-error > etiquetas que indican ningún error o ningún error. Luego se transforma en un formato dependiente del dispositivo / proveedor, elimina las etiquetas del espacio de nombres, etc.

La respuesta finalmente se recibe de la siguiente manera:

[(regresa, [(usuario, regresa), (uid, 928), (nombre\_clase, superusuario), (contraseña, abc123 @ # $ # $ ^)])]