El conjunto de documentos para este producto aspira al uso de un lenguaje no discriminatorio. A los fines de esta documentación, "no discriminatorio" se refiere al lenguaje que no implica discriminación por motivos de edad, discapacidad, género, identidad de raza, identidad étnica, orientación sexual, nivel socioeconómico e interseccionalidad. Puede haber excepciones en la documentación debido al lenguaje que se encuentra ya en las interfaces de usuario del software del producto, el lenguaje utilizado en función de la documentación de la RFP o el lenguaje utilizado por un producto de terceros al que se hace referencia. Obtenga más información sobre cómo Cisco utiliza el lenguaje inclusivo.
Cisco ha traducido este documento combinando la traducción automática y los recursos humanos a fin de ofrecer a nuestros usuarios en todo el mundo contenido en su propio idioma. Tenga en cuenta que incluso la mejor traducción automática podría no ser tan precisa como la proporcionada por un traductor profesional. Cisco Systems, Inc. no asume ninguna responsabilidad por la precisión de estas traducciones y recomienda remitirse siempre al documento original escrito en inglés (insertar vínculo URL).
No hay requisitos específicos para este documento.
La información que contiene este documento se basa en las siguientes versiones de software y hardware.
switch(config)# feature nxsdk
switch(config)# feature bash-shell
switch(config)# run bash
bash-4.2$ vi /isan/bin/nxsdk-app.py
Nota: Se recomienda crear archivos Python en el directorio /isan/bin/. Los archivos Python necesitan permisos de ejecución para ejecutarse - no coloque archivos Python en el directorio /bootflash ni en ninguno de sus subdirectorios.
Nota: No es necesario crear y editar archivos Python mediante NX-OS. El desarrollador puede crear la aplicación utilizando su entorno local y transferir los archivos completados al dispositivo mediante un protocolo de transferencia de archivos de su elección. Sin embargo, podría ser más eficaz para el desarrollador depurar y solucionar los problemas del script mediante las utilidades de NX-OS.
Función sdkThread
Nota: A partir de NX-SDK v1.5.0, se puede pasar un tercer parámetro booleano al método NxSdk.getSdkInst, que habilita las excepciones avanzadas cuando es True y deshabilita las excepciones avanzadas cuando es False. Este método se documenta aquí .
Algunos de los métodos más utilizados son:
Nota: Los formatos de datos R_JSON y R_XML sólo funcionan si el comando admite la salida en esos formatos. En NX-OS, puede verificar si un comando admite la salida en un formato de datos concreto canalizando la salida al formato de datos solicitado. Si el comando piped devuelve un resultado significativo, se soporta ese formato de datos. Por ejemplo, si ejecuta show mac address-table dynamic | json en NX-OS devuelve la salida JSON, entonces el formato de datos R_JSON también es compatible con NX-SDK.
Algunos métodos opcionales que pueden resultar útiles son:
N9K-C93180LC-EX# show Tra?
track Tracking information
Transceiver_DOM.py Returns all interfaces with DOM-capable transceivers inserted
En una aplicación Python con el uso de NX-SDK, se crean y definen comandos CLI personalizados dentro de la función sdkThread. Existen dos tipos de comandos: Mostrar comandos y comandos Config.
Estos dos métodos permiten la creación de los comandos show y config respectivamente:
Nota: Este comando es una subclase de cliP.newCliCmd("cmd_type", "cmd_name", "sintaxis") donde cmd_type es CONF_CMD o SHOW_CMD (dependiendo del tipo de comando que se esté configurando), cmd_name es un nombre único para el comando interno de la aplicación NX-SDK personalizada y sintaxis describe qué palabras clave y parámetros se pueden utilizar en el comando. Debido a esto, la documentación de la API para este comando puede ser más útil como referencia.
Nota: Este comando es una subclase de cliP.newCliCmd("cmd_type", "cmd_name", "sintaxis") donde cmd_type es CONF_CMD o SHOW_CMD (depende del tipo de comando que se configure), cmd_name es un nombre único para el comando interno de la aplicación NX-SDK personalizada, y la sintaxis describe qué palabras clave y parámetros se pueden utilizar en el comando. Debido a esto, la documentación de la API para este comando puede ser más útil como referencia.
Ambos tipos de comandos tienen dos componentes diferentes: Parámetros y palabras clave:
1. Los parámetros son valores que se utilizan para cambiar los resultados del comando. Por ejemplo, en el comando show ip route 192.168.1.0, hay una palabra clave route seguida de un parámetro que acepta una dirección IP, que especifica que sólo se deben mostrar las rutas que incluyen la dirección IP proporcionada.
2. Palabras clave cambian los resultados del comando a través de su sola presencia. Por ejemplo, en el comando show mac address-table dynamic, hay una palabra clave dynamic, que especifica que sólo se mostrarán las direcciones MAC aprendidas dinámicamente.
Ambos componentes se definen en la sintaxis de un comando de NX-SDK cuando se crea. Existen métodos para que el objeto NxCliCmd modifique la implementación específica de ambos componentes.
Para ver ejemplos de código de los componentes de comandos más utilizados, vea la sección Ejemplos de Comandos CLI Personalizados de este documento.
Una vez creados los comandos CLI personalizados, es necesario crear un objeto de la clase pyCmdHandler que se describe más adelante en este documento y establecerlo como objeto de controlador de devolución de llamada CLI para el objeto NxCliParser. Esto se demuestra de la siguiente manera:
cmd_handler = pyCmdHandler()
cliP.setCmdHandler(cmd_handler)
A continuación, es necesario agregar el objeto NxCliParser al árbol del analizador de CLI de NX-OS para que el usuario pueda ver los comandos de CLI personalizados. Esto se realiza con el comando cliP.addToParseTree(), donde cliP es el objeto NxCliParser devuelto por el método sdk.getCliParser().
Ejemplo de la Función sdkThread
A continuación se muestra un ejemplo de una función sdkThread típica con el uso de las funciones explicadas anteriormente. Esta función (entre otras dentro de una aplicación típica de Python de NX-SDK personalizada) utiliza variables globales, de las que se crean instancias al ejecutar scripts.
cliP = ""
sdk = ""
event_hdlr = ""
tmsg = ""
def sdkThread():
global cliP, sdk, event_hdlr, tmsg
sdk = nx_sdk_py.NxSdk.getSdkInst(len(sys.argv), sys.argv)
if not sdk:
return
sdk.setAppDesc("Returns all interfaces with DOM-capable transceivers inserted")
tmsg = sdk.getTracer()
tmsg.event("[{}] Started service".format(sdk.getAppName()))
cliP = sdk.getCliParser()
nxcmd = cliP.newShowCmd("show_port_bw_util_cmd", "port bw utilization [<port>]")
nxcmd.updateKeyword("port", "Port Information")
nxcmd.updateKeyword("bw", "Port Bandwidth Information")
nxcmd.updateKeyword("utilization", "Port BW utilization in (%)")
nxcmd.updateParam("<port>", "Optional Filter Port Ex) Ethernet1/1", nx_sdk_py.P_INTERFACE)
nxcmd1 = cliP.newConfigCmd("port_bw_threshold_cmd", "port bw threshold <threshold>")
nxcmd1.updateKeyword("threshold", "Port BW Threshold in (%)")
int_attr = nx_sdk_py.cli_param_type_integer_attr()
int_attr.min_val = 1;
int_attr.max_val = 100;
nxcmd1.updateParam("<threshold>", "Threshold Limit. Default 50%", nx_sdk_py.P_INTEGER, int_attr, len(int_attr))
mycmd = pyCmdHandler()
cliP.setCmdHandler(mycmd)
cliP.addToParseTree()
sdk.startEventLoop()
# If sdk.stopEventLoop() is called or application is removed from VSH...
tmsg.event("Service Quitting...!")
nx_sdk_py.NxSdk.__swig_destroy__(sdk)
La clase pyCmdHandler se hereda de la clase NxCmdHandler dentro de la biblioteca nx_sdk_py. El método postCliCb(self, clicmd) definido dentro de la clase pyCmdHandler se llama siempre que se llaman comandos CLI que se originan desde una aplicación NX-SDK. Por lo tanto, el método postCliCb(self, clicmd) es donde se define cómo se comportan en el dispositivo los comandos CLI personalizados definidos en la función sdkThread.
La función postCliCb(self, clicmd) devuelve un valor Boolean. Si se devuelve True, se supone que el comando se ha ejecutado correctamente. False debe devolverse si el comando no se ejecutó correctamente por cualquier motivo.
El parámetro clicmd utiliza el nombre único que se definió para el comando cuando se creó en la función sdkThread. Por ejemplo, si crea un nuevo comando show con un nombre único de show_xcvr_dom, se recomienda hacer referencia a este comando con el mismo nombre en la función postCliCb(self, clicmd) después de comprobar si el nombre del argumento clicmd contiene show_xcvr_dom. Se demuestra aquí:
def sdkThread():
<snip>
sh_xcvr_dom = cliP.newShowCmd("show_xcvr_dom", "dom")
sh_xcvr_dom.updateKeyword("dom", "Show all interfaces with transceivers that are DOM-capable")
</snip>
class pyCmdHandler(nx_sdk_py.NxCmdHandler):
def postCliCb(self, clicmd):
if "show_xcvr_dom" in clicmd.getCmdName():
get_dom_capable_interfaces()
Si se crea un comando que utiliza parámetros, lo más probable es que necesite utilizar esos parámetros en algún momento de la función postCliCb(self, clicmd). Esto se puede hacer con el método clicmd.getParamValue("<parámetro>"), donde <parámetro> es el nombre del parámetro de comando del que desea obtener el valor entre corchetes angulares (<>). Este método se documenta aquí. Sin embargo, el valor devuelto por esta función debe convertirse al tipo que necesita. Esto se puede hacer con estos métodos:
La función postCliCb(self, clicmd) (o cualquier función posterior) también será normalmente donde se imprime el resultado del comando show en la consola. Esto se hace con el método clicmd.printConsole().
Nota: Si la aplicación encuentra un error, una excepción no controlada o se cierra repentinamente de algún otro modo, la salida de la función clicmd.printConsole() no se mostrará en absoluto. Por esta razón, la práctica recomendada al depurar la aplicación Python es registrar los mensajes de depuración en el syslog con el uso de un objeto NxTrace devuelto por el método sdk.getTracer() o utilizar instrucciones print y ejecutar la aplicación a través del binario /isan/bin/python del shell de Bash.
Ejemplo de la Clase pyCmdHandler
El código siguiente sirve como ejemplo de la clase pyCmdHandler descrita anteriormente. Este código se toma del archivo ip_move.py en la aplicación ip-move NX-SDK disponible aquí. El objetivo de esta aplicación es realizar un seguimiento del movimiento de una dirección IP definida por el usuario a través de las interfaces de un dispositivo Nexus. Para hacer esto, el código encuentra la dirección MAC de la entrada de dirección IP a través del parámetro <ip> dentro de la memoria caché ARP del dispositivo, luego verifica en qué VLAN reside esa dirección MAC usando la tabla de direcciones MAC del dispositivo. Con este MAC y VLAN, el comando show system internal l2fm l2dbg macdb address <mac> vlan <vlan> muestra una lista de índices de interfaz SNMP con los que se ha asociado recientemente esta combinación. A continuación, el código utiliza el comando show interface snmp-ifindex para traducir los índices de interfaz SNMP recientes a nombres de interfaz legibles por el usuario.
class pyCmdHandler(nx_sdk_py.NxCmdHandler):
def postCliCb(self, clicmd):
global cli_parser
if "show_ip_movement" in clicmd.getCmdName():
target_ip = nx_sdk_py.void_to_string(clicmd.getParamValue("<ip>"))
target_mac = get_mac_from_arp(cli_parser, clicmd, target_ip)
mac_vlan = ""
if target_mac:
mac_vlan = get_vlan_from_cam(cli_parser, clicmd, target_mac)
if mac_vlan:
find_mac_movement(cli_parser, clicmd, target_mac, mac_vlan)
else:
print("No entires in MAC address table")
clicmd.printConsole("No entries in MAC address table for {}".format(target_mac))
else:
clicmd.printConsole("No entries in ARP table for {}".format(target_ip))
return True
def get_mac_from_arp(cli_parser, clicmd, target_ip):
exec_cmd = "show ip arp {}".format(target_ip)
arp_cmd = cli_parser.execShowCmd(exec_cmd, nx_sdk_py.R_JSON)
if arp_cmd:
try:
arp_json = json.loads(arp_cmd)
except ValueError as exc:
return None
count = int(arp_json["TABLE_vrf"]["ROW_vrf"]["cnt-total"])
if count:
intf = arp_json["TABLE_vrf"]["ROW_vrf"]["TABLE_adj"]["ROW_adj"]
if intf.get("ip-addr-out") == target_ip:
target_mac = intf["mac"]
clicmd.printConsole("{} is currently present in ARP table, MAC address {}\n".format(target_ip, target_mac))
return target_mac
else:
return None
else:
return None
else:
return None
def get_vlan_from_cam(cli_parser, clicmd, target_mac):
exec_cmd = "show mac address-table address {}".format(target_mac)
mac_cmd = cli_parser.execShowCmd(exec_cmd, nx_sdk_py.R_JSON)
if mac_cmd:
try:
cam_json = json.loads(mac_cmd)
except ValueError as exc:
return None
mac_entry = cam_json["TABLE_mac_address"]["ROW_mac_address"]
if mac_entry:
if mac_entry["disp_mac_addr"] == target_mac:
egress_intf = mac_entry["disp_port"]
mac_vlan = mac_entry["disp_vlan"]
clicmd.printConsole("{} is currently present in MAC address table on interface {}, VLAN {}\n".format(target_mac, egress_intf, mac_vlan))
return mac_vlan
else:
return None
else:
return None
else:
return None
def find_mac_movement(cli_parser, clicmd, target_mac, mac_vlan):
exec_cmd = "show system internal l2fm l2dbg macdb address {} vlan {}".format(target_mac, mac_vlan)
l2fm_cmd = cli_parser.execShowCmd(exec_cmd)
if l2fm_cmd:
event_re = re.compile(r"^\s+(\w{3}) (\w{3}) (\d+) (\d{2}):(\d{2}):(\d{2}) (\d{4}) (0x\S{8}) (\d+)\s+(\S+) (\d+)\s+(\d+)\s+(\d+)")
unique_interfaces = []
l2fm_events = l2fm_cmd.splitlines()
for line in l2fm_events:
res = re.search(event_re, line)
if res:
day_name = res.group(1)
month = res.group(2)
day = res.group(3)
hour = res.group(4)
minute = res.group(5)
second = res.group(6)
year = res.group(7)
if_index = res.group(8)
db = res.group(9)
event = res.group(10)
src=res.group(11)
slot = res.group(12)
fe = res.group(13)
if "MAC_NOTIF_AM_MOVE" in event:
timestamp = "{} {} {} {}:{}:{} {}".format(day_name, month, day, hour, minute, second, year)
intf_dict = {"if_index": if_index, "timestamp": timestamp}
unique_interfaces.append(intf_dict)
if not unique_interfaces:
clicmd.printConsole("No entries for {} in L2FM L2DBG\n".format(target_mac))
if len(unique_interfaces) == 1:
clicmd.printConsole("{} has not been moving between interfaces\n".format(target_mac))
if len(unique_interfaces) > 1:
clicmd.printConsole("{} has been moving between the following interfaces, from most recent to least recent:\n".format(target_mac))
unique_interfaces = get_snmp_intf_index(unique_interfaces)
clicmd.printConsole("\t{} - {} (Current interface)\n".format(unique_interfaces[-1]["timestamp"], unique_interfaces[-1]["intf_name"]))
for intf in unique_interfaces[-2::-1]:
clicmd.printConsole("\t{} - {}\n".format(intf["timestamp"], intf["intf_name"]))
def get_snmp_intf_index(if_index_dict_list):
global cli_parser
snmp_ifindex = cli_parser.execShowCmd("show interface snmp-ifindex", nx_sdk_py.R_JSON)
snmp_ifindex_json = json.loads(snmp_ifindex)
snmp_ifindex_list = snmp_ifindex_json["TABLE_interface"]["ROW_interface"]
for index_dict in if_index_dict_list:
index = index_dict["if_index"]
for ifindex_json in snmp_ifindex_list:
if index == ifindex_json["snmp-ifindex"]:
index_dict["intf_name"] = ifindex_json["interface"]
return if_index_dict_list
En esta sección se muestran algunos ejemplos del parámetro de sintaxis utilizado al crear comandos CLI personalizados con los métodos cliP.newShowCmd() o cliP.newConfigCmd(), donde cliP es el objeto NxCliParser devuelto por el método sdk.getCliParser().
Nota: La compatibilidad con la sintaxis con paréntesis de apertura y cierre ("(" y ")") se introduce en NX-SDK v1.5.0, incluido en NX-OS versión 7.0(3)I7(3). Se supone que el usuario utiliza NX-SDK v1.5.0 cuando sigue cualquiera de estos ejemplos que incluyen sintaxis utilizando paréntesis de apertura y cierre.
Este comando show toma una sola palabra clave mac y agrega una cadena auxiliar de Shows all misprogrammed MAC addresses on this device to the keyword.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "mac")
nx_cmd.updateKeyword("mac", "Shows all misprogrammed MAC addresses on this device")
Este comando show toma un único parámetro <mac>. Los corchetes angulares alrededor de la palabra mac significan que este es un parámetro. Se agrega al parámetro una cadena auxiliar de dirección MAC para comprobar si hay errores de programación. El parámetro nx_sdk_py.P_MAC_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro como una dirección MAC, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed_mac", "<mac>")
nx_cmd.updateParam("<mac>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
Este comando show opcionalmente puede tomar una sola palabra clave [mac]. Los corchetes que encierran la palabra mac significan que esta palabra clave es opcional. Se agrega a la palabra clave una cadena auxiliar de Shows all misprogrammed MAC addresses on this device.
nx_cmd = cliP.newShowCmd( "show_misprogrammed_mac" , "[mac]" )
nx_cmd.updateKeyword( "mac" , "Shows all misprogrammed MAC addresses on this device" )
Este comando show opcionalmente puede tomar un solo parámetro [<mac>]. Los corchetes que encierran la palabra < mac > significan que este parámetro es opcional. Los corchetes angulares alrededor de la palabra mac significan que este es un parámetro. Se agrega al parámetro una cadena auxiliar de dirección MAC para comprobar si hay errores de programación. El parámetro nx_sdk_py.P_MAC_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro como una dirección MAC, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed_mac", "[<mac>]")
nx_cmd.updateParam("<mac>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
Este comando show toma una sola palabra clave mac inmediatamente seguida por el parámetro <mac-address>. Los corchetes angulares alrededor de la palabra mac-address significan que éste es un parámetro. Se agrega a la palabra clave una cadena auxiliar de Comprobar la dirección MAC para detectar errores de programación. Se agrega al parámetro una cadena auxiliar de dirección MAC para comprobar si hay errores de programación. El parámetro nx_sdk_py.P_MAC_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro como una dirección MAC, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "mac <mac-address>")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
Este comando show puede tomar una de dos palabras clave, las cuales tienen dos parámetros diferentes a continuación. La primera palabra clave mac tiene un parámetro de <mac-address>, y la segunda palabra clave ip tiene un parámetro de <ip-address>. Los corchetes angulares alrededor de las palabras mac-address e ip-address significan que son parámetros. Se agrega una cadena auxiliar de Verificar la dirección MAC para la programación incorrecta a la palabra clave mac. Se agrega una cadena auxiliar de dirección MAC para verificar si hay programas erróneos al parámetro <mac-address>. El parámetro nx_sdk_py.P_MAC_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro <mac-address> como una dirección MAC, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP. Se agrega a la palabra clave ip una cadena auxiliar de Comprobar la dirección IP para la programación incorrecta. Se agrega una cadena de ayudante de dirección IP para verificar si hay programas erróneos al parámetro <ip-address>. El parámetro nx_sdk_py.P_IP_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro <ip-address> como una dirección IP, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "(mac <mac-address> | ip <ip-address>)")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
nx_cmd.updateKeyword("ip", "Check IP address for misprogramming")
nx_cmd.updateParam("<ip-address>", "IP address to check for misprogramming", nx_sdk_py.P_IP_ADDR)
Este comando show puede tomar una de dos palabras clave, las cuales tienen dos parámetros diferentes a continuación. La primera palabra clave mac tiene un parámetro de <mac-address>, y la segunda palabra clave ip tiene un parámetro de <ip-address>. Los corchetes angulares alrededor de las palabras mac-address e ip-address significan que son parámetros. Se agrega una cadena auxiliar de Verificar la dirección MAC para la programación incorrecta a la palabra clave mac. Se agrega una cadena auxiliar de dirección MAC para verificar si hay programas erróneos al parámetro <mac-address>. El parámetro nx_sdk_py.P_MAC_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro <mac-address> como una dirección MAC, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP. Se agrega a la palabra clave ip una cadena auxiliar de Comprobar la dirección IP para la programación incorrecta. Se agrega una cadena de ayudante de dirección IP para verificar si hay programas erróneos al parámetro <ip-address>. El parámetro nx_sdk_py.P_IP_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro <ip-address> como una dirección IP, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP. Este comando show podría tomar opcionalmente una palabra clave [clear]. A esta palabra clave opcional se agrega una cadena de ayudante Clears addresses detected to be misprogrammed .
nx_cmd = cliP.newShowCmd("show_misprogrammed", "(mac <mac-address> | ip <ip-address>) [clear]")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
nx_cmd.updateKeyword("ip", "Check IP address for misprogramming")
nx_cmd.updateParam("<ip-address>", "IP address to check for misprogramming", nx_sdk_py.P_IP_ADDR)
nx_cmd.updateKeyword("clear", "Clears addresses detected to be misprogrammed")
Este comando show puede tomar una de dos palabras clave, las cuales tienen dos parámetros diferentes a continuación. La primera palabra clave mac tiene un parámetro de <mac-address>, y la segunda palabra clave ip tiene un parámetro de <ip-address>. Los corchetes angulares alrededor de las palabras mac-address e ip-address significan que son parámetros. Se agrega una cadena auxiliar de Comprobar la dirección MAC para errores de programación a la palabra clave mac. Se agrega una cadena auxiliar de dirección MAC para verificar si hay programas erróneos al parámetro <mac-address>. El parámetro nx_sdk_py.P_MAC_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro <mac-address> como una dirección MAC, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP. Se agrega a la palabra clave ip una cadena auxiliar de Comprobar la dirección IP para la programación incorrecta. Se agrega una cadena de ayudante de dirección IP para verificar si hay programas erróneos al parámetro <ip-address>. El parámetro nx_sdk_py.P_IP_ADDR en el método nx_cmd.updateParam() se utiliza para definir el tipo del parámetro <ip-address> como una dirección IP, lo que evita que el usuario final ingrese otro tipo, como una cadena, un entero o una dirección IP. Este comando show podría tomar opcionalmente un parámetro [<module>]. Una cadena de ayudante Solamente se agregan direcciones claras en el módulo especificado a este parámetro opcional.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "(mac <mac-address> | ip <ip-address>) [<module>]")
nx_cmd.updateKeyword("mac", "Check MAC address for misprogramming")
nx_cmd.updateParam("<mac-address>", "MAC address to check for misprogramming", nx_sdk_py.P_MAC_ADDR)
nx_cmd.updateKeyword("ip", "Check IP address for misprogramming")
nx_cmd.updateParam("<ip-address>", "IP address to check for misprogramming", nx_sdk_py.P_IP_ADDR)
nx_cmd.updateParam("<module>", "Clears addresses detected to be misprogrammed", nx_sdk_py.P_INTEGER)
Una vez que se ha creado una aplicación Python de NX-SDK, a menudo será necesario depurarla. NX-SDK le informa en caso de que haya errores de sintaxis en su código, pero debido a que la biblioteca de Python NX-SDK utiliza SWIG para traducir bibliotecas de C++ a bibliotecas de Python, cualquier excepción encontrada en el momento de la ejecución del código resulta en un volcado de núcleo de aplicación similar a este:
terminate called after throwing an instance of 'Swig::DirectorMethodException'
what(): SWIG director method error. Error detected when calling 'NxCmdHandler.postCliCb'
Aborted (core dumped)
Debido a la naturaleza ambigua de este mensaje de error, la práctica recomendada para depurar aplicaciones Python es registrar los mensajes de depuración en el syslog con el uso de un objeto NxTrace devuelto por el método sdk.getTracer(). Esto se demuestra de la siguiente manera:
#! /isan/bin/python
tracer = 0
def evt_thread():
<snip>
tracer = sdk.getTracer()
tracer.event("[NXSDK-APP][INFO] Started service")
<snip>
class pyCmdHandler(nx_sdk_py.NxCmdHandler):
def postCliCb(self, clicmd):
global tracer
tracer.event("[NXSDK-APP][DEBUG] Received command: {}".format(clicmd))
if "show_test_command" in clicmd.getCmdName():
tracer.event("[NXSDK-APP][DEBUG] `show_test_command` recognized")
Si el registro de mensajes de depuración en el syslog no es una opción, un método alternativo es utilizar sentencias print y ejecutar la aplicación a través del binario /isan/bin/python del shell de Bash. Sin embargo, el resultado de estas instrucciones de impresión sólo será visible cuando se ejecuten de esta manera; la ejecución de la aplicación a través del shell de VSH no produce ningún resultado. A continuación se muestra un ejemplo de cómo utilizar las declaraciones impresas:
#! /isan/bin/python
tracer = 0
def evt_thread():
<snip>
print("[NXSDK-APP][INFO] Started service")
<snip>
class pyCmdHandler(nx_sdk_py.NxCmdHandler):
def postCliCb(self, clicmd):
print("[NXSDK-APP][DEBUG] Received command: {}".format(clicmd))
if "show_test_command" in clicmd.getCmdName():
print("[NXSDK-APP][DEBUG] `show_test_command` recognized")
Una vez que una aplicación Python se ha probado completamente en el shell de Bash y está lista para su implementación, la aplicación debe instalarse en producción a través de VSH. Esto permite que la aplicación persista cuando el dispositivo se recarga o cuando se produce el cambio del sistema en un escenario de supervisor dual. Para implementar una aplicación a través de VSH, debe crear un paquete RPM con el uso de un entorno de compilación de NX-SDK y ENXOS SDK. Cisco DevNet proporciona una imagen de Docker que permite crear fácilmente paquetes RPM.
Nota: Si necesita ayuda para instalar Docker en su sistema operativo específico, consulte la documentación de instalación de Docker.
En un host compatible con Docker, extraiga la versión de imagen que elija con el comando docker pull docckercisco/nxsdk:<tag> , donde <tag> es la etiqueta de la versión de imagen que elija. Aquí puede ver las versiones de las imágenes disponibles y sus etiquetas correspondientes. Esto se demuestra con la etiqueta v1 aquí:
docker pull dockercisco/nxsdk:v1
Inicie un contenedor llamado nxsdk desde esta imagen y adjúntelo. Si la etiqueta de su elección es diferente, sustituya la v1 por la etiqueta:
docker run -it --name nxsdk dockercisco/nxsdk:v1 /bin/bash
Actualice a la última versión de NX-SDK y navegue hasta el directorio NX-SDK, luego extraiga los últimos archivos de git:
cd /NX-SDK/
git pull
Si necesita utilizar una versión anterior de NX-SDK, puede clonar la rama de NX-SDK con la etiqueta de versión correspondiente con el comando git clone -b v<version> https://github.com/CiscoDevNet/NX-SDK.git, donde <version> es la versión de NX-SDK que necesita. Esto se demuestra aquí con NX-SDK v1.0.0:
cd /
rm -rf /NX-SDK
git clone -b v1.0.0 https://github.com/CiscoDevNet/NX-SDK.git
A continuación, transfiera la aplicación Python al contenedor Docker. Hay algunas maneras diferentes de hacerlo.
root@2dcbe841742a:~# exit
[root@localhost ~]# docker cp /app/python_app.py nxsdk:/root/
[root@localhost ~]# docker start nxsdk
nxsdk
[root@localhost ~]# docker attach nxsdk
root@2dcbe841742a:/# ls /root/
python_app.py
A continuación, utilice el script rpm_gen.py ubicado en /NX-SDK/scripts/ para crear un paquete RPM desde la aplicación Python. Esta secuencia de comandos tiene un argumento obligatorio y dos modificadores necesarios:
Nota: El nombre de archivo no necesita contener ninguna extensión de archivo, como .py. En este ejemplo, si el nombre de archivo fuera python_app en lugar de python_app.py, el paquete RPM se generaría sin problemas.
Aquí se muestra el uso del script rpm_gen.py.
root@7bfd1714dd2f:~# python /NX-SDK/scripts/rpm_gen.py test_python_app -s /root/ -u #################################################################################################### Generating rpm package... <snip> RPM package has been built #################################################################################################### SPEC file: /NX-SDK/rpm/SPECS/test_python_app.spec RPM file : /NX-SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm
La ruta de archivo al paquete RPM se indica en la línea final de la salida del script rpm_gen.py. Este archivo debe copiarse del contenedor Docker en el host para que pueda transferirse al dispositivo Nexus en el que desea ejecutar la aplicación. Después de salir del contenedor Docker, se puede hacer fácilmente con el comando docker cp <container>:<container_filepath> <host_filepath>, donde <container> es el nombre del contenedor Docker de NX-SDK (en este caso, nxsdk), <container_filepath> es la ruta de archivo completa del paquete RPM dentro del contenedor (en este caso, /NX-SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm), y <host_filepath> es la ruta de archivo completa de nuestro host Docker al que se va a transferir el paquete RPM (en este caso, /root/). Este comando se muestra aquí:
root@7bfd1714dd2f:/# exit [root@localhost ~]# docker cp nxsdk:/NX-SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm /root/ [root@localhost ~]# ls /root/ anaconda-ks.cfg test_python_app-1.0-1.0.0.x86_64.rpm
Transfiera este paquete RPM al dispositivo Nexus con el método de transferencia de archivos que prefiera. Una vez que el paquete RPM está en el dispositivo, se debe instalar y activar de manera similar a un SMU. Esto se demuestra de la siguiente manera, bajo la suposición de que el paquete RPM fue transferido a la memoria de inicialización del dispositivo.
N9K-C93180LC-EX# install add bootflash:test_python_app-1.0-1.0.0.x86_64.rpm [####################] 100% Install operation 27 completed successfully at Tue May 8 06:40:13 2018 N9K-C93180LC-EX# install activate test_python_app-1.0-1.0.0.x86_64 [####################] 100% Install operation 28 completed successfully at Tue May 8 06:40:20 2018
Nota: Cuando instale el paquete RPM con el comando install add, incluya el dispositivo de almacenamiento y el nombre de archivo exacto del paquete. Cuando active el paquete RPM después de la instalación, no incluya el dispositivo de almacenamiento y el nombre de archivo; utilice el nombre del paquete en sí. Puede verificar el nombre del paquete con el comando show install inactive.
Una vez activado el paquete RPM, puede iniciar la aplicación con NX-SDK con el comando de configuración nxsdk service <application-name>, donde <application-name> es el nombre del nombre de archivo de Python (y, posteriormente, la aplicación) que se definió cuando se utilizó anteriormente el script rpm_gen.py. Esto se demuestra de la siguiente manera:
N9K-C93180LC-EX# conf Enter configuration commands, one per line. End with CNTL/Z. N9K-C93180LC-EX(config)# nxsdk service-name test_python_app % This could take some time. "show nxsdk internal service" to check if your App is Started & Runnning
Puede verificar que la aplicación esté activa y haya comenzado a ejecutarse con el comando show nxsdk internal service:
N9K-C93180LC-EX# show nxsdk internal service NXSDK Started/Temp unavailabe/Max services : 1/0/32 NXSDK Default App Path : /isan/bin/nxsdk NXSDK Supported Versions : 1.0 Service-name Base App Started(PID) Version RPM Package ------------------------- --------------- ----------------- ---------- ------------------------ test_python_app nxsdk_app4 VSH(23195) 1.0 test_python_app-1.0-1.0.0.x86_64
También puede verificar que los comandos CLI personalizados creados por esta aplicación estén accesibles en NX-OS:
N9K-C93180LC-EX# show test? test_python_app Nexus Sdk Application
Comentarios