Zabbix ローレベルディスカバリ（LLD）の拡張③ NW機器のifDescrとifAlias(＝Discription)を一緒に取得

 [Zabbix ローレベルディスカバリ（LLD）の拡張①](http://qiita.com/usiusi/items/51e8478cb080412958a4)
 [Zabbix ローレベルディスカバリ（LLD）の拡張②](http://qiita.com/usiusi/items/d616b7c0d51a926ca4a0)
 [Zabbix ローレベルディスカバリ（LLD）の拡張③](http://qiita.com/usiusi/items/0972da38984a82e43e74)
 [Zabbix ローレベルディスカバリ（LLD）の拡張④](http://qiita.com/usiusi360/items/8d44fd6b975b2db40ded)
 [Zabbix ローレベルディスカバリ（LLD）の拡張⑤](http://qiita.com/usiusi360/items/4664b10426bb6d993e1d)


> *追記*
>　Zabbix3.0ではLLDアイテムキーを「discovery[{#IFDESCR}, ifDescr, {#IFALIAS}, ifAlias]」とすることで複数同時取得が可能になりましたので、本対応は不要になります。
> ■ 3.4 Discovery of SNMP OIDs
> https://www.zabbix.com/documentation/3.0/manual/discovery/low_level_discovery#discovery_of_snmp_oids

#NW機器へのローレベルディスカバリでifDescrとifAlias(＝Discription)を一緒に取得する
アラート発生時に対向機器が直ぐに分かるよう、スイッチのコンフィグにDiscriptionを設定していることが多いと思いますが、Zabbix標準で用意されているsnmp機器用のローレベルディスカバリアイテムでは、以下の理由からifDescrとifAliasを一緒に取得することができません。

ローレベルディスカバリの「タイプ：snmpエージェント」で取得できるのは、{#SNMPVALUE}　{#SNMPINDEX}の2つ。
{#SNMPVALUE}にはキーに設定したものの”値”がセットされます。

例えば「ifDescr」を指定すれば、{#SNMPVALUE}は「FastEthernet 0/1」のような文字列がセットされます。

{#SNMPINDEX}が項目「SNMP OID」で必須であることからキーに設定できるものは実質1つのため、取得キーを「ifDescr」にすると、「ifAlias（＝Discription）」が取れません。
逆に「ifAlias（＝Discription）」を取得キーにすると、「ifDescr」が取れないというジレンマに陥ります。

「ifDescr」と「ifAlias（＝Discription）」とindex番号を一度に取得したい場合、「外部チェック」機能と自前のスクリプトで実装することで実現できます。

#### WebGUIでの設定

| ディスカバリルール| | 
|:--------|------------:|:------------:|
|名前      |snmpディスカバリ |
|タイプ    |外部チェック |
|キー      |snmp.port.discovery.sh[{$SNMP_COMMUNITY},{HOST.IP}] |

※外部チェックに使用するスクリプトはフルパスで書いても無視されるので、zabbix_server.confの「ExternalScripts=」で定義し、その下にスクリプトを配置します。

※{$SNMP_COMMUNITY}の部分はグローバルマクロ/テンプレートマクロ/ホストマクロの何れかで定義しておきます。

| アイテムのプロトタイプ| | 
|:-----------|------------:|:------------:|
|名前         |ネットワークトラフィック[{#IF_DESCR}-IN / Description:{#IF_NAME}]|
|タイプ       |snmpv1エージェント |
|キー         |ifInOctets[{#IF_INDEX}] |
|SNMP OID    |ifInOctets.{#IF_INDEX} |



```bash:snmp.port.discovery.sh

#!/bin/bash

C_STRING=$1
if [ "${C_STRING}" = "" ] ;then
    echo "NO ARGUMENT"
    echo "### ./snmp.port.discovery.sh [community string] [target ip]"
    exit 1
fi

TARGET=$2
if [ "${TARGET}" = "" ] ;then
    echo "NO ARGUMENT"
    echo "### ./snmp.port.discovery.sh [community string] [target ip]"
    exit 1
fi

IFS=$'\n'
array1=(`snmpwalk -c ${C_STRING} -v 1 ${TARGET} IF-MIB::ifIndex | cut -d ":" -f4 | sed 's/^ //g'`)
if [ "${array1[1]}" = "" ] ;then
    echo "ZBX_NOTSUPPORTED"
    exit 1
fi

array2=(`snmpwalk -c ${C_STRING} -v 1 ${TARGET} IF-MIB::ifDescr | cut -d ":" -f4 | sed 's/^ //g'`)
array3=(`snmpwalk -c ${C_STRING} -v 1 ${TARGET} IF-MIB::ifAlias | cut -d ":" -f4 `)

echo "{"
echo "  \"data\":["

FIRST=1
i=0

for VER in ${array1[@]}
do
  if [ ${FIRST} -eq 1 ] ; then
     echo ""
     FIRST=0
  else
     echo ","
  fi

  if [ "${array3[i]}" = " " ] ;then
     array3[i]=Unknown
  else
     array3[i]=`echo "${array3[i]}" | sed 's/^ //g' `
  fi

  echo -e -n "\t\t{ \"{#IF_INDEX}\":\"${array1[i]}\",\"{#IF_DESCR}\":\"${array2[i]}\",\"{#IF_NAME}\":\"${array3[i]}\" }"

  i=${i}+1

done

echo ""
echo "  ]"
echo "}"

```

```lang:スクリプトに引数を付けて実行すると、以下のように返す。
# ./snmp.port.discovery.sh public 192.168.0.1
{
  "data":[
       { "{#IF_INDEX}":"1","{#IF_DESCR}":"Vlan1","{#IF_NAME}":"Unknown" },
       { "{#IF_INDEX}":"52","{#IF_DESCR}":"Vlan52","{#IF_NAME}":"Unknown" },
       { "{#IF_INDEX}":"5001","{#IF_DESCR}":"Port-channel1","{#IF_NAME}":"< FEC to host01 >" },
       { "{#IF_INDEX}":"10001","{#IF_DESCR}":"FastEthernet0/1","{#IF_NAME}":"< db01 #1 >" },
       { "{#IF_INDEX}":"10002","{#IF_DESCR}":"FastEthernet0/2","{#IF_NAME}":"< app01 #1 >" },
       { "{#IF_INDEX}":"10003","{#IF_DESCR}":"FastEthernet0/3","{#IF_NAME}":"< web01 #0 >" }
　 ]
}
```

#### LLDでの検出結果

ポートを発見すると以下のように自動的に実ポート名とDiscriptionが、アイテム名及びトリガー名に入った状態で表示されるため判別しやすくなります。

![LDD_nw.png](https://qiita-image-store.s3.amazonaws.com/0/54952/ab80d798-6224-b408-f225-aa35022936f9.png)