O conjunto de documentação deste produto faz o possível para usar uma linguagem imparcial. Para os fins deste conjunto de documentação, a imparcialidade é definida como uma linguagem que não implica em discriminação baseada em idade, deficiência, gênero, identidade racial, identidade étnica, orientação sexual, status socioeconômico e interseccionalidade. Pode haver exceções na documentação devido à linguagem codificada nas interfaces de usuário do software do produto, linguagem usada com base na documentação de RFP ou linguagem usada por um produto de terceiros referenciado. Saiba mais sobre como a Cisco está usando a linguagem inclusiva.
A Cisco traduziu este documento com a ajuda de tecnologias de tradução automática e humana para oferecer conteúdo de suporte aos seus usuários no seu próprio idioma, independentemente da localização. Observe que mesmo a melhor tradução automática não será tão precisa quanto as realizadas por um tradutor profissional. A Cisco Systems, Inc. não se responsabiliza pela precisão destas traduções e recomenda que o documento original em inglês (link fornecido) seja sempre consultado.
Não existem requisitos específicos para este documento.
As informações neste documento são baseadas nestas versões de software e hardware:
switch(config)# feature nxsdk
switch(config)# feature bash-shell
switch(config)# run bash
bash-4.2$ vi /isan/bin/nxsdk-app.py
Note: A prática recomendada é criar arquivos Python no diretório /isan/bin/. Os arquivos Python precisam de permissões de execução para serem executados - não coloque os arquivos Python no diretório /bootflash nem em nenhum de seus subdiretórios.
Note: Não é necessário criar e editar arquivos Python por meio do NX-OS. O desenvolvedor pode criar o aplicativo usando seu ambiente local e transferir os arquivos concluídos para o dispositivo usando um protocolo de transferência de arquivos de sua escolha. No entanto, pode ser mais eficiente para o desenvolvedor depurar e solucionar problemas em seus scripts usando utilitários NX-OS.
Função sdkThread
Note: A partir do NX-SDK v1.5.0, um terceiro parâmetro Boolean pode ser passado para o método NxSdk.getSdkInst, que habilita Exceções avançadas quando True e desabilita Exceções avançadas quando False. Este método está documentado aqui .
Alguns métodos comumente usados incluem:
Note: Os formatos de dados R_JSON e R_XML só funcionarão se o comando suportar saída nesses formatos. No NX-OS, você pode verificar se um comando oferece suporte à saída em um formato de dados específico canalizando a saída para o formato de dados solicitado. Se o comando piped retornar uma saída significativa, esse formato de dados será suportado. Por exemplo, se você executar show mac address-table dynamic | json no NX-OS retorna a saída JSON e, em seguida, o formato de dados R_JSON também é suportado no NX-SDK.
Alguns métodos opcionais que podem ser úteis são:
N9K-C93180LC-EX# show Tra?
track Tracking information
Transceiver_DOM.py Returns all interfaces with DOM-capable transceivers inserted
Em um aplicativo Python com o uso do NX-SDK, comandos CLI personalizados são criados e definidos na função sdkThread. Há dois tipos de comandos: Comandos show e comandos Config.
Esses dois métodos permitem a criação de comandos show e comandos config, respectivamente:
Note: Este comando é uma subclasse de cliP.newCliCmd("cmd_type", "cmd_name", "syntax") onde cmd_type é CONF_CMD ou SHOW_CMD (dependendo do tipo de comando sendo configurado), cmd_name é um nome exclusivo para o comando interno ao aplicativo NX-SDK personalizado e syntax descreve quais palavras-chave e parâmetros podem ser usados no comando. Por causa disso, a documentação da API para esse comando pode ser mais útil para referência.
Note: Este comando é uma subclasse de cliP.newCliCmd("cmd_type", "cmd_name", "syntax") onde cmd_type é CONF_CMD ou SHOW_CMD (depende do tipo de comando configurado), cmd_name é um nome exclusivo para o comando interno ao aplicativo NX-SDK personalizado e sintaxe descreve quais palavras-chave e parâmetros podem ser usados no comando. Por causa disso, a documentação da API para esse comando pode ser mais útil para referência.
Os dois tipos de comandos têm dois componentes diferentes: Parâmetros e Palavras-chave:
1. Parâmetros são valores usados para alterar os resultados do comando. Por exemplo, no comando show ip route 192.168.1.0, há uma palavra-chave route seguida por um parâmetro que aceita um endereço IP, que especifica que somente as rotas que incluem o endereço IP fornecido devem ser mostradas.
2. As palavras-chave alteram os resultados do comando apenas por meio de sua presença. Por exemplo, no comando show mac address-table dynamic, há uma palavra-chave dynamic, que especifica que somente endereços MAC aprendidos dinamicamente devem ser exibidos.
Ambos os componentes são definidos na sintaxe de um comando do NX-SDK quando ele é criado. Existem métodos para o objeto NxCliCmd para modificar a implementação específica de ambos os componentes.
Para visualizar exemplos de código de componentes de comando usados com frequência, consulte a seção Exemplos de comandos CLI personalizados deste documento.
Após a criação dos comandos CLI personalizados, um objeto da classe pyCmdHandler, descrito posteriormente neste documento, precisa ser criado e definido como o objeto do manipulador de retorno de chamada CLI para o objeto NxCliParser. Isso é demonstrado da seguinte forma:
cmd_handler = pyCmdHandler()
cliP.setCmdHandler(cmd_handler)
Em seguida, o objeto NxCliParser precisa ser adicionado à árvore do analisador CLI do NX-OS para que os comandos CLI personalizados fiquem visíveis para o usuário. Isso é feito com o comando cliP.addToParseTree(), onde cliP é o objeto NxCliParser retornado pelo método sdk.getCliParser().
Exemplo de Função sdkThread
Aqui está um exemplo de uma função sdkThread típica com o uso das funções explicadas anteriormente. Esta função (entre outras dentro de um aplicativo NX-SDK Python personalizado típico) utiliza variáveis globais, que são instanciadas na execução de script.
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)
A classe pyCmdHandler é herdada da classe NxCmdHandler na biblioteca nx_sdk_py. O método postCliCb(self, clicmd) definido na classe pyCmdHandler é chamado sempre que os comandos CLI que se originam de um aplicativo NX-SDK. Assim, o método postCliCb(self, clicmd) é onde você define como os comandos CLI personalizados definidos na função sdkThread se comportam no dispositivo.
A função postCliCb(self, clicmd) retorna um valor booleano. Se True for retornado, presume-se que o comando foi executado com êxito. False deverá ser retornado se o comando não tiver sido executado com êxito por qualquer motivo.
O parâmetro clicmd usa o nome exclusivo que foi definido para o comando quando ele foi criado na função sdkThread. Por exemplo, se você criar um novo comando show com um nome exclusivo de show_xcvr_dom, é recomendável consultar esse comando com o mesmo nome na função postCliCb(self, clicmd) depois de verificar se o nome do argumento clicmd contém show_xcvr_dom. É demonstrado aqui:
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()
Se um comando que utiliza parâmetros for criado, você provavelmente precisará usar esses parâmetros em algum momento na função postCliCb(self, clicmd). Isso pode ser feito com o método clicmd.getParamValue("<parâmetro>"), onde <parâmetro> é o nome do parâmetro de comando que você deseja obter o valor entre colchetes angulares (<>). Este método está documentado aqui. No entanto, o valor retornado por essa função precisa ser convertido no tipo de que você precisa. Isso pode ser feito com estes métodos:
A função postCliCb(self, clicmd) (ou qualquer função subsequente) também será normalmente onde a saída do comando show é impressa no console. Isso é feito com o método clicmd.printConsole().
Note: Se o aplicativo encontrar um erro, uma exceção não tratada ou sair repentinamente, a saída da função clicmd.printConsole() não será exibida. Por esse motivo, a prática recomendada ao depurar seu aplicativo Python é registrar mensagens de depuração no syslog com o uso de um objeto NxTrace retornado pelo método sdk.getTracer() ou usar instruções de impressão e executar o aplicativo através do binário /isan/bin/python do shell Bash.
Exemplo de classe pyCmdHandler
O código a seguir serve de exemplo para a classe pyCmdHandler descrita acima. Esse código é extraído do arquivo ip_move.py no aplicativo NX-SDK ip-motion disponível aqui. A finalidade dessa aplicação é rastrear o movimento de um endereço IP definido pelo usuário através das interfaces de um dispositivo Nexus. Para fazer isso, o código localiza o endereço MAC da entrada do endereço IP por meio do parâmetro <ip> no cache ARP do dispositivo e verifica em qual VLAN esse endereço MAC reside usando a tabela de endereços MAC do dispositivo. Usando esse MAC e VLAN, o comando show system internal l2fm l2dbg macdb address <mac> vlan <vlan> exibe uma lista de índices de interface SNMP aos quais essa combinação foi recentemente associada. Em seguida, o código usa o comando show interface snmp-ifindex para converter índices de interface SNMP recentes em nomes de interface legíveis por humanos.
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
Esta seção mostra alguns exemplos do parâmetro de sintaxe usado quando você cria comandos CLI personalizados com os métodos cliP.newShowCmd() ou cliP.newConfigCmd(), em que cliP é o objeto NxCliParser retornado pelo método sdk.getCliParser().
Note: O suporte para sintaxe com parênteses de abertura e fechamento ("(" e ")") é introduzido no NX-SDK v1.5.0, incluído no NX-OS Versão 7.0(3)I7(3). Supõe-se que o usuário utilize o NX-SDK v1.5.0 quando ele seguir qualquer um desses exemplos fornecidos que incluem sintaxe utilizando parênteses de abertura e fechamento.
Este comando show usa uma única palavra-chave mac e adiciona uma string de ajuda de Mostra todos os endereços MAC mal programados neste dispositivo à palavra-chave.
nx_cmd = cliP.newShowCmd("show_misprogrammed", "mac")
nx_cmd.updateKeyword("mac", "Shows all misprogrammed MAC addresses on this device")
Este comando show recebe um único parâmetro <mac>. Os colchetes angulares delimitadores em torno da palavra mac significam que este é um parâmetro. Uma cadeia de caracteres auxiliar de endereço MAC para verificar erros de programação é adicionada ao parâmetro. O parâmetro nx_sdk_py.P_MAC_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro como um endereço MAC, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço 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 pode, opcionalmente, ter uma única palavra-chave [mac]. Os colchetes ao redor da palavra mac significam que essa palavra-chave é opcional. Uma cadeia de caracteres auxiliar de Mostra todos os endereços MAC mal programados neste dispositivo é adicionada à palavra-chave.
nx_cmd = cliP.newShowCmd( "show_misprogrammed_mac" , "[mac]" )
nx_cmd.updateKeyword( "mac" , "Shows all misprogrammed MAC addresses on this device" )
Este comando show pode, opcionalmente, ter um único parâmetro [<mac>]. Os colchetes ao redor da palavra < mac > significam que esse parâmetro é opcional. Os colchetes angulares delimitadores em torno da palavra mac significam que este é um parâmetro. Uma cadeia de caracteres auxiliar de endereço MAC para verificar erros de programação é adicionada ao parâmetro. O parâmetro nx_sdk_py.P_MAC_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro como um endereço MAC, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço 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)
Esse comando show usa uma única palavra-chave mac imediatamente seguida pelo parâmetro <mac-address>. Os colchetes angulares delimitadores em torno da palavra mac-address significam que este é um parâmetro. Uma cadeia de caracteres auxiliar de Verificar endereço MAC para erros de programação é adicionada à palavra-chave. Uma cadeia de caracteres auxiliar de endereço MAC para verificar erros de programação é adicionada ao parâmetro. O parâmetro nx_sdk_py.P_MAC_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro como um endereço MAC, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço 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)
Esse comando show pode usar uma das duas palavras-chave, que têm dois parâmetros diferentes seguindo-as. A primeira palavra-chave mac tem um parâmetro de <mac-address>, e a segunda palavra-chave ip tem um parâmetro de <ip-address>. Os colchetes angulares delimitadores em torno das palavras mac-address e ip-address significam que são parâmetros. Uma cadeia de caracteres auxiliar de Verificar endereço MAC para erros de programação é adicionada à palavra-chave mac. Uma cadeia de caracteres auxiliar de endereço MAC para verificar erros de programação é adicionada ao parâmetro <mac-address>. O parâmetro nx_sdk_py.P_MAC_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro <mac-address> como um endereço MAC, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço IP. Uma cadeia de caracteres auxiliar de Verificar endereço IP para erro de programação é adicionada à palavra-chave ip. Uma cadeia de caracteres auxiliar de endereço IP para verificar erros de programação é adicionada ao parâmetro <ip-address>. O parâmetro nx_sdk_py.P_IP_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro <ip-address> como um endereço IP, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço 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)
Esse comando show pode usar uma das duas palavras-chave, que têm dois parâmetros diferentes seguindo-as. A primeira palavra-chave mac tem um parâmetro de <mac-address>, e a segunda palavra-chave ip tem um parâmetro de <ip-address>. Os colchetes angulares delimitadores em torno das palavras mac-address e ip-address significam que são parâmetros. Uma cadeia de caracteres auxiliar de Verificar endereço MAC para erros de programação é adicionada à palavra-chave mac. Uma cadeia de caracteres auxiliar de endereço MAC para verificar erros de programação é adicionada ao parâmetro <mac-address>. O parâmetro nx_sdk_py.P_MAC_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro <mac-address> como um endereço MAC, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço IP. Uma cadeia de caracteres auxiliar de Verificar endereço IP para erro de programação é adicionada à palavra-chave ip. Uma cadeia de caracteres auxiliar de endereço IP para verificar erros de programação é adicionada ao parâmetro <ip-address>. O parâmetro nx_sdk_py.P_IP_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro <ip-address> como um endereço IP, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço IP. Esse comando show pode usar opcionalmente uma palavra-chave [clear]. Uma cadeia de caracteres auxiliar Limpa endereços detectados para serem mal programados é adicionada a essa palavra-chave opcional.
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")
Esse comando show pode usar uma das duas palavras-chave, que têm dois parâmetros diferentes seguindo-as. A primeira palavra-chave mac tem um parâmetro de <mac-address>, e a segunda palavra-chave ip tem um parâmetro de <ip-address>. Os colchetes angulares delimitadores em torno das palavras mac-address e ip-address significam que são parâmetros. Uma cadeia de caracteres auxiliar de Verificar endereço MAC para erros de programação é adicionada à palavra-chave mac. Uma cadeia de caracteres auxiliar de endereço MAC para verificar erros de programação é adicionada ao parâmetro <mac-address>. O parâmetro nx_sdk_py.P_MAC_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro <mac-address> como um endereço MAC, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço IP. Uma cadeia de caracteres auxiliar de Verificar endereço IP para erro de programação é adicionada à palavra-chave ip. Uma cadeia de caracteres auxiliar de endereço IP para verificar erros de programação é adicionada ao parâmetro <ip-address>. O parâmetro nx_sdk_py.P_IP_ADDR no método nx_cmd.updateParam() é usado para definir o tipo do parâmetro <ip-address> como um endereço IP, o que impede a entrada do usuário final de outro tipo, como uma string, um inteiro ou um endereço IP. Este comando show pode, opcionalmente, receber um parâmetro [<module>]. Uma cadeia de caracteres auxiliar Somente endereços não criptografados no módulo especificado são adicionados 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)
Depois que um aplicativo NX-SDK Python tiver sido criado, ele frequentemente precisará ser depurado. O NX-SDK o informa caso haja algum erro de sintaxe em seu código, mas como a biblioteca Python NX-SDK utiliza o SWIG para converter bibliotecas C++ em bibliotecas Python, quaisquer exceções encontradas no momento da execução do código resultam em um dump central de aplicativo semelhante 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)
Devido à natureza ambígua dessa mensagem de erro, a prática recomendada para depurar aplicativos Python é registrar mensagens de depuração no syslog com o uso de um objeto NxTrace retornado pelo método sdk.getTracer(). Isso é demonstrado da seguinte forma:
#! /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")
Se o registro de mensagens de depuração no syslog não for uma opção, um método alternativo será usar instruções de impressão e executar o aplicativo através do binário /isan/bin/python do shell Bash. No entanto, a saída dessas instruções de impressão só será visível quando executada dessa maneira - executar o aplicativo através do shell do VSH não produz nenhuma saída. Um exemplo de utilização de instruções de impressão é mostrado aqui:
#! /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")
Quando um aplicativo Python tiver sido totalmente testado no shell Bash e estiver pronto para implantação, o aplicativo deverá ser instalado na produção através do VSH. Isso permite que o aplicativo persista quando o dispositivo é recarregado ou quando ocorre um switchover de sistema em um cenário de supervisor duplo. Para implantar um aplicativo por meio do VSH, você precisa criar um pacote RPM com o uso de um ambiente de compilação NX-SDK e ENXOS SDK. O Cisco DevNet fornece uma imagem Docker que permite a fácil criação de pacotes RPM.
Note: Para obter assistência para instalar o Docker em seu sistema operacional específico, consulte a documentação de instalação do Docker.
Em um host com capacidade para Docker, use a versão de imagem de sua escolha com o comando docker pull dockercisco/nxsdk:<tag> , onde <tag> é a marca da versão de imagem de sua escolha. Você pode visualizar as versões de imagem disponíveis e suas tags correspondentes aqui. Isso é demonstrado com a marca v1 aqui:
docker pull dockercisco/nxsdk:v1
Inicie um contêiner chamado nxsdk a partir desta imagem e anexe-o. Se a tag de sua escolha for diferente, substitua v1 por sua tag:
docker run -it --name nxsdk dockercisco/nxsdk:v1 /bin/bash
Atualize para a versão mais recente do NX-SDK, navegue para o diretório NX-SDK e extraia os arquivos mais recentes do git:
cd /NX-SDK/
git pull
Se precisar usar uma versão mais antiga do NX-SDK, você pode clonar a ramificação do NX-SDK com o uso da respectiva marca de versão com o comando git clone -b v<version> https://github.com/CiscoDevNet/NX-SDK.git, onde <version> é a versão do NX-SDK necessária. Isso é demonstrado aqui com o NX-SDK v1.0.0:
cd /
rm -rf /NX-SDK
git clone -b v1.0.0 https://github.com/CiscoDevNet/NX-SDK.git
Em seguida, transfira o aplicativo Python para o contêiner Docker. Há algumas maneiras diferentes de fazer isso.
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
Em seguida, use o script rpm_gen.py localizado em /NX-SDK/scripts/ para criar um pacote RPM do aplicativo Python. Este script tem um argumento necessário e dois switches necessários:
Note: O nome de arquivo não precisa conter nenhuma extensão de arquivo, como .py. Neste exemplo, se o nome do arquivo fosse python_app em vez de python_app.py, o pacote RPM seria gerado sem problemas.
O uso do script rpm_gen.py é demonstrado aqui.
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
O caminho do arquivo para o pacote RPM é indicado na linha final da saída do script rpm_gen.py. Esse arquivo deve ser copiado do contêiner Docker para o host para que possa ser transferido para o dispositivo Nexus no qual você deseja executar o aplicativo. Depois de sair do contêiner do Docker, isso pode ser feito facilmente com o comando docker cp <contêiner>:<container_filepath> <host_filepath>, onde <contêiner> é o nome do contêiner do Docker do NX-SDK (nesse caso, nxsdk), <container_filepath> é o caminho de arquivo completo do pacote RPM dentro do contêiner (nesse caso, /NX-SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm) e <host_filepath> é o caminho de arquivo completo em nosso host Docker para o qual o pacote RPM deve ser transferido (nesse caso, /root/). Este comando é demonstrado aqui:
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
Transfira esse pacote RPM para o dispositivo Nexus com o uso do método de transferência de arquivo preferido. Quando o pacote RPM estiver no dispositivo, ele deverá ser instalado e ativado de forma semelhante a um SMU. Isso é demonstrado da seguinte forma, supondo que o pacote RPM foi transferido para o flash de inicialização do 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
Note: Ao instalar o pacote RPM com o comando install add, inclua o dispositivo de armazenamento e o nome de arquivo exato do pacote. Quando você ativar o pacote RPM após a instalação, não inclua o dispositivo de armazenamento e o nome do arquivo - use o nome do próprio pacote. Você pode verificar o nome do pacote com o comando show install inative.
Depois que o pacote RPM estiver ativado, você poderá iniciar o aplicativo com o NX-SDK com o comando de configuração nxsdk service <application-name>, onde <application-name> é o nome do arquivo Python (e, subsequentemente, o aplicativo) que foi definido quando o script rpm_gen.py foi usado anteriormente. Isso é demonstrado da seguinte forma:
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
Você pode verificar se o aplicativo está ativo e se começou a ser executado com o 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
Você também pode verificar se os comandos CLI personalizados criados por esse aplicativo estão acessíveis no NX-OS:
N9K-C93180LC-EX# show test? test_python_app Nexus Sdk Application
Feedback