この製品のドキュメントセットは、偏向のない言語を使用するように配慮されています。このドキュメントセットでの偏向のない言語とは、年齢、障害、性別、人種的アイデンティティ、民族的アイデンティティ、性的指向、社会経済的地位、およびインターセクショナリティに基づく差別を意味しない言語として定義されています。製品ソフトウェアのユーザインターフェイスにハードコードされている言語、RFP のドキュメントに基づいて使用されている言語、または参照されているサードパーティ製品で使用されている言語によりドキュメントに例外が存在する場合があります。シスコのインクルーシブ ランゲージの取り組みの詳細は、こちらをご覧ください。
シスコは世界中のユーザにそれぞれの言語でサポート コンテンツを提供するために、機械と人による翻訳を組み合わせて、本ドキュメントを翻訳しています。ただし、最高度の機械翻訳であっても、専門家による翻訳のような正確性は確保されません。シスコは、これら翻訳の正確性について法的責任を負いません。原典である英語版(リンクからアクセス可能)もあわせて参照することを推奨します。
このドキュメントに特有の要件はありません。
このドキュメントの情報は、次のソフトウェアとハードウェアのバージョンに基づいています。
switch(config)# feature nxsdk
switch(config)# feature bash-shell
switch(config)# run bash
bash-4.2$ vi /isan/bin/nxsdk-app.py
注:ベストプラクティスは、Pythonファイルを/isan/bin/ディレクトリに作成することです。Pythonファイルを実行するには、実行権限が必要です。Pythonファイルを/bootflashディレクトリやサブディレクトリに配置しないでください。
注:NX-OSからPythonファイルを作成および編集する必要はありません。開発者は、自分のローカル環境を使用してアプリケーションを作成し、完成したファイルを自分の選択したファイル転送プロトコルを使用してデバイスに転送することができます。ただし、開発者がNX-OSユーティリティを使用してスクリプトをデバッグおよびトラブルシューティングする方が効率的な場合があります。
sdkThread関数
注:NX-SDK v1.5.0から、3番目のブール型パラメータをNxSdk.getSdkInstメソッドに渡すことができます。このメソッドは、Trueの場合は拡張例外を有効にし、Falseの場合は拡張例外を無効にします。この方法は、ここに記載されています。
一般的に使用される方法には、次のものがあります。
注:R_JSONおよびR_XMLのデータ形式は、コマンドがこれらの形式の出力をサポートする場合にのみ機能します。NX-OSでは、コマンドが特定のデータ形式の出力をサポートしているかどうかを確認するために、要求されたデータ形式に出力をパイプで渡すことができます。pipedコマンドが意味のある出力を返す場合、そのデータ形式がサポートされます。たとえば、show mac address-table dynamic | NX-OSのjsonはJSON出力を返し、R_JSONデータ形式はNX-SDKでもサポートされます。
便利なオプションの方法は次のとおりです。
N9K-C93180LC-EX# show Tra?
track Tracking information
Transceiver_DOM.py Returns all interfaces with DOM-capable transceivers inserted
NX-SDKを使用するPythonアプリケーションでは、カスタムCLIコマンドがsdkThread関数で作成および定義されます。次の2種類のコマンドがあります。showコマンド、およびConfigコマンド。
次の2つの方法により、それぞれshowコマンドとconfigコマンドを作成できます。
注:このコマンドは、cliP.newCliCmd("cmd_type", "cmd_name", "syntax")のサブクラスで、cmd_typeはCONF_CMDまたはSHOW_CMD(設定するコマンドのタイプに応じる)ですSDKアプリケーションおよび構文は、コマンドで使用できるキーワードとパラメータを説明します。このため、このコマンドのAPIドキュメントは、より参考になります。
注:このコマンドは、cliP.newCliCmd("cmd_type", "cmd_name", "syntax")のサブクラスで、cmd_typeはCONF_CMDまたはSHOW_CMD(設定されているコマンドのタイプに応じて異なる)ですnx-SDKアプリケーションおよび構文は、コマンドで使用できるキーワードとパラメータを示します。このため、このコマンドのAPIドキュメントは、より参考になります。
どちらのタイプのコマンドにも、次の2つの異なるコンポーネントがあります。パラメータとキーワード:
1.パラメータは、コマンドの結果を変更するために使用される値です。たとえば、show ip route 192.168.1.0コマンドでは、routeキーワードが続き、IPアドレスを受け入れるパラメータが指定されています。このパラメータは、指定されたIPアドレスを含むルートだけを表示することを指定します。
2.キーワードは、コマンドの結果をキーワードだけで変更します。たとえば、show mac address-table dynamicコマンドには、動的に学習されたMACアドレスのみを表示することを指定するdynamicキーワードがあります。
どちらのコンポーネントも、作成時にNX-SDKコマンドの構文で定義されます。NxCliCmdオブジェクトには、両方のコンポーネントの特定の実装を変更するためのメソッドがあります。
よく使用されるコマンドコンポーネントのコード例を表示するには、このドキュメントの「カスタムCLIコマンドの例」セクションを参照してください。
カスタムCLIコマンドを作成した後、このドキュメントで後述するpyCmdHandlerクラスのオブジェクトを作成し、NxCliParserオブジェクトのCLIコールバックハンドラオブジェクトとして設定する必要があります。これは次のように示されています。
cmd_handler = pyCmdHandler()
cliP.setCmdHandler(cmd_handler)
次に、カスタムCLIコマンドがユーザに表示されるように、NxCliParserオブジェクトをNX-OS CLIパーサツリーに追加する必要があります。これはcliP.addToParseTree()コマンドで行われます。ここで、cliPはsdk.getCliParser()メソッドによって返されるNxCliParserオブジェクトです。
sdkThread関数の例
以下は、前述の関数を使用した一般的なsdkThread関数の例です。この関数(一般的なカスタムNX-SDK Pythonアプリケーション内の他の関数など)は、グローバル変数を使用します。グローバル変数は、スクリプトの実行時にインスタンス化されます。
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)
pyCmdHandlerクラスは、nx_sdk_pyライブラリ内のNxCmdHandlerクラスから継承されます。pyCmdHandlerクラス内で定義されたpostCliCb(self, clicmd)メソッドは、NX-SDKアプリケーションから発信されるCLIコマンドのたびに呼び出されます。したがって、postCliCb(self, clicmd)メソッドは、sdkThread関数で定義されたカスタムCLIコマンドがデバイスでどのように動作するかを定義します。
postCliCb(self, clicmd)関数はブール値を返します。Trueが返された場合は、コマンドが正常に実行されたと見なされます。何らかの理由でコマンドが正常に実行されなかった場合は、Falseを返します。
clicmdパラメータは、sdkThread関数で作成されたときにコマンドに定義された一意の名前を使用します。たとえば、show_xcvr_domという一意の名前を持つ新しいshowコマンドを作成する場合は、clicmd引数の名前にshow_xcvr_domが含まれているかどうかを確認した後、postCliCb(self, clicmd)関数)でをで同同同じ名前でこのコマンドをコマンドを参照することをお勧勧めします。次に示します。
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()
パラメータを利用するコマンドが作成された場合、ほとんどの場合、postCliCb(self, clicmd)関数の中の任意の時点でこれらのパラメータを使用する必要があります。これを行うには、clicmd.getParamValue("<parameter>")メソッドを使用します。ここで、<parameter>は、角カッコ(<>)で囲まれた値を取得するコマンドパラメータの名前です。 この方法は、ここに記載されています。ただし、この関数から返される値は、必要な型に変換する必要があります。これは、次の方法で実行できます。
postCliCb(self, clicmd)関数(または後続の関数)は、通常、showコマンドの出力がコンソールに出力される場所でもあります。これはclicmd.printConsole()メソッドで行います。
注:アプリケーションでエラーが発生した場合、処理されない例外が発生した場合、または突然終了した場合、clicmd.printConsole()関数からの出力はまったく表示されません。このため、Pythonアプリケーションをデバッグする際のベストプラクティスは、sdk.getTracer()メソッドで返されたNxTraceオブジェクトを使用してデバッグメッセージをsyslogに記録するか、print文を使用してBashシェルの/isan/bin/pythonバイナリでアプリケーションをを実行します。
pyCmdHandlerクラスの例
次のコードは、上記のpyCmdHandlerクラスの例として機能します。このコードは、ここで入手可能なip-movement NX-SDKアプリケーションのip_move.pyファイルから取得したものです。このアプリケーションの目的は、Nexusデバイスのインターフェイス間でのユーザ定義IPアドレスの移動を追跡することです。このため、コードはデバイスのARPキャッシュ内の<ip>パラメータを介して入力されたIPアドレスのMACアドレスを見つけ、そのMACアドレスがデバイスのMACアドレステーブルを使用して存在するVLANを確認します。このMACおよびVLANを使用して、show system internal l2fm l2dbg macdb address <mac> vlan <vlan>コマンドを実行すると、この組み合わせが最近関連付けられたSNMPインターフェイスインデックスのリストが表示されます。次に、show interface snmp-ifindexコマンドを使用して、最近のSNMPインターフェイスインデックスを人間が読みやすいインターフェイス名に変換します。
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
このセクションでは、cliP.newShowCmd()メソッドまたはcliP.newConfigCmd()メソッドを使用してカスタムCLIコマンドを作成する際に使用する構文パラメータの例を示します。cliPはCliParser()メソッドでは ..
注:カッコ("("および")")を開く構文のサポートは、NX-OSリリース7.0(3)I7(3)に含まれるNX-SDK v1.5.0で導入されました。 ユーザがNX-SDK v1.5.0を使用していることを前提としています。この例では、開きカッコと閉じカッコを使用した構文が含まれています。
このshowコマンドは、単一のキーワードmacを取得し、「Show all misprogrammed MAC addresses on this device」というヘルパーストリングをキーワードに追加します。
nx_cmd = cliP.newShowCmd("show_misprogrammed", "mac")
nx_cmd.updateKeyword("mac", "Shows all misprogrammed MAC addresses on this device")
このshowコマンドは、単一のパラメータ<mac>を使用します。macという単語の周りの角カッコは、これがパラメータであることを示します。パラメータに、プログラミングの誤りをチェックするためのMACアドレスのヘルパ文字列が追加されます。nx_cmd.updateParam()メソッドのnx_sdk_py.P_MAC_ADDRパラメータは、パラメータのタイプをMACアドレスとして定義するために使用します。これにより、文字列、整数、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)
このshowコマンドでは、オプションで1つのキーワード[mac]を使用できます。macという単語の前後の角カッコは、このキーワードがオプションであることを示します。「Show 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" )
このshowコマンドでは、オプションで1つのパラメータ[<mac>]を使用できます。「< mac >」の前後の角カッコは、このパラメータがオプションであることを示します。macという単語の周りの角カッコは、これがパラメータであることを示します。パラメータに、プログラミングの誤りをチェックするためのMACアドレスのヘルパ文字列が追加されます。nx_cmd.updateParam()メソッドのnx_sdk_py.P_MAC_ADDRパラメータは、パラメータのタイプをMACアドレスとして定義するために使用します。これにより、文字列、整数、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)
このshowコマンドは、単一のキーワードmacの直後にパラメータ<mac-address>を指定します。「mac-address」という単語の周囲の角カッコは、これがパラメータであることを示します。Check MAC address for misprogrammingのヘルパーストリングがキーワードに追加されます。パラメータに、プログラミングの誤りをチェックするためのMACアドレスのヘルパ文字列が追加されます。nx_cmd.updateParam()メソッドのnx_sdk_py.P_MAC_ADDRパラメータは、パラメータのタイプをMACアドレスとして定義するために使用されます。これにより、文字列、整数、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)
このshowコマンドは、2つのキーワードのいずれかを使用できます。両方のキーワードの後に2つの異なるパラメータがあります。第1キーワードmacはパラメータ<mac-address>を有し、第2キーワードipはパラメータ<ip-address>を有する。「mac-address」および「ip-address」という単語の前後の角カッコ([()])は、これらがパラメータであることを示します。Check MAC address for misprogrammingのヘルパーストリングがmacキーワードに追加されます。<mac-address>パラメータに、プログラミングの誤りをチェックするためのMACアドレスのヘルパー文字列を追加します。nx_cmd.updateParam()メソッドのnx_sdk_py.P_MAC_ADDRパラメータは、MACアドレスとして<mac-address>パラメータのタイプを定義するために使用されます。これにより、エンドユーザは文字列、整数、IPアドレスなどの別のタイプを入力できません。Check IP address for misprogrammingのヘルパーストリングがipキーワードに追加されます。<ip-address>パラメータに、プログラミングの誤りをチェックするためのIPアドレスのヘルパー文字列を追加します。nx_cmd.updateParam()メソッドのnx_sdk_py.P_IP_ADDR.パラメータは、IPアドレスとして<ip-address>パラメータの型を定義するために使用されます。これにより、エンドユーザは文字列、整数、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)
このshowコマンドは、2つのキーワードのいずれかを使用できます。両方のキーワードの後に2つの異なるパラメータがあります。第1キーワードmacは<mac-address>のパラメータを有し、第2キーワードipは<ip-address>のパラメータを有する。「mac-address」および「ip-address」という単語の前後の角カッコ([()])は、これらがパラメータであることを示します。Check MAC address for misprogrammingのヘルパーストリングがmacキーワードに追加されます。<mac-address>パラメータに、プログラミングの誤りをチェックするためのMACアドレスのヘルパー文字列を追加します。nx_cmd.updateParam()メソッドのnx_sdk_py.P_MAC_ADDRパラメータは、MACアドレスとして<mac-address>パラメータのタイプを定義するために使用されます。これにより、エンドユーザは文字列、整数、IPアドレスなどの別のタイプを入力できません。Check IP address for misprogrammingのヘルパーストリングがipキーワードに追加されます。<ip-address>パラメータに、プログラミングの誤りをチェックするためのIPアドレスのヘルパー文字列を追加します。nx_cmd.updateParam()メソッドのnx_sdk_py.P_IP_ADDR.パラメータは、IPアドレスとして<ip-address>パラメータの型を定義するために使用されます。これにより、エンドユーザは文字列、整数、IPアドレスなどの別の型を入力できません。このshowコマンドでは、オプションでキーワード[clear]を使用できます。このオプションのキーワードに、誤ってプログラムされたことが検出されたアドレスをクリアするヘルパーストリングが追加されます。
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")
このshowコマンドは、2つのキーワードのいずれかを使用できます。両方のキーワードの後に2つの異なるパラメータがあります。第1キーワードmacは<mac-address>のパラメータを有し、第2キーワードipは<ip-address>のパラメータを有する。「mac-address」および「ip-address」という単語の前後の角カッコ([()])は、これらがパラメータであることを示します。Check MAC address for misprogrammingのヘルパーストリングがmacキーワードに追加されます。<mac-address>パラメータに、プログラミングの誤りをチェックするためのMACアドレスのヘルパー文字列を追加します。nx_cmd.updateParam()メソッドのnx_sdk_py.P_MAC_ADDRパラメータは、MACアドレスとして<mac-address>パラメータのタイプを定義するために使用されます。これにより、エンドユーザは文字列、整数、IPアドレスなどの別のタイプを入力できません。Check IP address for misprogrammingのヘルパーストリングがipキーワードに追加されます。<ip-address>パラメータに、プログラミングの誤りをチェックするためのIPアドレスのヘルパー文字列を追加します。nx_cmd.updateParam()メソッドのnx_sdk_py.P_IP_ADDR.パラメータは、IPアドレスとして<ip-address>パラメータの型を定義するために使用されます。これにより、エンドユーザは文字列、整数、IPアドレスなどの別の型を入力できません。このshowコマンドでは、オプションでパラメータ[<module>]を使用できます。ヘルパー文字列Only clear addresses on specified moduleがこのオプションパラメータに追加されます。
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)
NX-SDK Pythonアプリケーションを作成したら、しばしばデバッグが必要になります。NX-SDKは、コードに構文エラーがある場合に通知しますが、Python NX-SDKライブラリはSWIGを使用してC++ライブラリをPythonライブラリに変換するため、コード実行時に発生した例外は次のようなアプリケーションコアダンプになります。
terminate called after throwing an instance of 'Swig::DirectorMethodException'
what(): SWIG director method error. Error detected when calling 'NxCmdHandler.postCliCb'
Aborted (core dumped)
このエラーメッセージの曖昧な性質により、Pythonアプリケーションをデバッグするベストプラクティスは、sdk.getTracer()メソッドによって返されるNxTraceオブジェクトを使用してデバッグメッセージをsyslogに記録することになります。これは次のように示されています。
#! /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")
デバッグメッセージをsyslogに記録するオプションがない場合は、print文を使用して、Bashシェルの/isan/bin/pythonバイナリを介してアプリケーションを実行する方法も使用します。ただし、これらのprint文からの出力は、この方法で実行した場合にのみ表示されます。VSHシェルを介してアプリケーションを実行しても出力は生成されません。print文の使用例を次に示します。
#! /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")
PythonアプリケーションがBashシェルで完全にテストされ、展開の準備ができたら、アプリケーションはVSHを使用して実稼働にインストールする必要があります。これにより、デバイスのリロード時、またはデュアルスーパーバイザシナリオでシステムのスイッチオーバーが発生した場合に、アプリケーションが保持されます。VSHを介してアプリケーションを展開するには、NX-SDKおよびENXOS SDKビルド環境を使用してRPMパッケージを作成する必要があります。Cisco DevNetは、RPMパッケージを簡単に作成できるDockerイメージを提供します。
注:特定のオペレーティングシステムにDockerをインストールする方法については、Dockerのインストールマニュアルを参照してください。
Docker対応のホストでは、docker pull dockercisco/nxsdk:<tag>コマンドを使用して任意のイメージバージョンをプルします。ここで<tag>は選択したイメージバージョンのタグです。利用可能なイメージバージョンと対応するタグはこちらで確認できます。これは、次のv1タグで示されています。
docker pull dockercisco/nxsdk:v1
このイメージからnxsdkという名前のコンテナを起動し、それにアタッチします。選択したタグが異なる場合は、タグをv1に置き換えます。
docker run -it --name nxsdk dockercisco/nxsdk:v1 /bin/bash
最新バージョンのNX-SDKに更新し、NX-SDKディレクトリに移動し、gitから最新ファイルを取得します。
cd /NX-SDK/
git pull
古いバージョンのNX-SDKを使用する必要がある場合は、git clone -b v<version> https://github.com/CiscoDevNet/NX-SDK.gitコマンドを使用して各バージョンタグを使用してNX-SDKブランチをクローニングできます。<version>は、必要なNX-SDKのバージョンです。これは、NX-SDK v1.0.0で示されています。
cd /
rm -rf /NX-SDK
git clone -b v1.0.0 https://github.com/CiscoDevNet/NX-SDK.git
次に、PythonアプリケーションをDockerコンテナに転送します。これを行う方法はいくつかあります。
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
次に、/NX-SDK/scripts/にあるrpm_gen.pyスクリプトを使用して、PythonアプリケーションからRPMパッケージを作成します。このスクリプトには、必要な引数が1つと、必要なスイッチが2つあります。
注:ファイル名には.pyのようなファイル拡張子を含める必要はありません。この例では、ファイル名がpython_app.pyではなくpython_appである場合、RPMパッケージは問題なく生成されます。
ここでは、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
RPMパッケージへのファイルパスは、rpm_gen.pyスクリプト出力の最終行に示されています。このファイルは、アプリケーションを実行するNexusデバイスに転送できるように、Dockerコンテナからホストにコピーする必要があります。Dockerコンテナを終了した後は、docker cp <container>:<container_filepath> <host_filepath>コマンドを使用して簡単に実行できます。ここで、<container>はNX-SDK Dockerコンテナの名前(この場合はnxsdk)で、<container_filepath>はコンテナ内内のRPMのパッケージのの全体です -SDK/rpm/RPMS/test_python_app-1.0-1.0.0.x86_64.rpm)および<host_filepath>は、RPMパッケージが転送されるDockerホスト上の完全なファイルパスです(この場合は/root/)。 次に、このコマンドを示します。
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
このRPMパッケージをNexusデバイスに転送するには、お好みのファイル転送方法を使用します。RPMパッケージがデバイスにインストールされたら、SMUと同様にインストールしてアクティブにする必要があります。これは、RPMパッケージがデバイスのブートフラッシュに転送されたことを前提として、次のように示されています。
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
注:install addコマンドを使用してRPMパッケージをインストールすると、ストレージデバイスとパッケージの正確なファイル名を含めます。インストール後にRPMパッケージをアクティブ化する場合は、ストレージデバイスとファイル名を含めないでください。パッケージ自体の名前を使用してください。show install inactiveコマンドを使用して、パッケージ名を確認できます。
RPMパッケージがアクティブになると、nxsdk service <application-name>設定コマンドを使用してNX-SDKでアプリケーションを起動できます。ここで、<application-name>はrpm_gen.pyスクリプトが使用された際に定義されたPythonのファイル名(そしてアプリケーション)です。これは次のように示されています。
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
アプリケーションが起動していて、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
また、このアプリケーションで作成されたカスタムCLIコマンドがNX-OSでアクセスできることを確認できます。
N9K-C93180LC-EX# show test? test_python_app Nexus Sdk Application
フィードバック