らくがきちょう

なんとなく

acitoolkit を使って Cisco ACI から Subnet 情報一覧を取得する

Cisco ACI 標準の Web 管理画面では Bridge Domain ごとに設定した Subnet 情報を一覧で見ることが出来ません。同一 Tenant 内であれば下図のように Bridge Domain 配下の Subnet をひとつひとつ展開し、アドレスを表示させる… ということも不可能ではありません。

f:id:sig9:20151025013109p:plain

ただし Bridge Domain の数が多くなれば「ひとつひとつ展開する」のは現実的ではありません。また、そもそも複数 Tenant の Bridge Domain / Subnet 情報を一度に表示させることは出来ません。そこで acitoolkit を使って「全 Tenant の Subnet 情報を一覧表示するスクリプト」を書いてみました。今回のスクリプトには以下のような特徴があります。

  1. 全 Tenant の Subnet 一覧を表示する
  2. Subnet が所属する Tenant / Application Profile / Bridge Domain 情報も一覧表示する
  3. Subnet の Scope 情報も表示する
  4. アドレスを持たない Bridge Domain 情報は「アドレス欄が空」として表示する
  5. 複数のアドレスを持つ Bridge Domain は、1 行 = 1 アドレスとして複数行表示する
  6. Bridge Domain が EPG に関連付けられていない場合は表示しない

Subnet 一覧を表示するスクリプト

acitoolkit を使うと極めてシンプルに書けます。acitoolkit に含まれる他のサンプルスクリプト同様、大部分は定形処理で、「Subnet のアドレスを取得する」という本質的な部分の記述はとても簡単に書けます。

#!/usr/bin/env python
import acitoolkit.acitoolkit as aci

def main():
    """
    Main show Subnets routine
    :return: None
    """
    # Login to APIC
    description = ('Simple application that logs on to the APIC'
                   ' and displays all of the Subnets.')
    creds = aci.Credentials('apic', description)
    args = creds.get()
    session = aci.Session(args.url, args.login, args.password)
    resp = session.login()
    if not resp.ok:
        print('%% Could not login to APIC')

    # Download all of the tenants, app profiles, and Subnets
    # and store the names as tuples in a list
    data = []
    tenants = aci.Tenant.get(session)
    for tenant in tenants:
        apps = aci.AppProfile.get(session, tenant)
        for app in apps:
           bds = aci.BridgeDomain.get(session, tenant)
           for bd in bds:
               subnets = aci.Subnet.get(session, bd, tenant)
               if len(subnets) == 0:
                   data.append((tenant.name, app.name, bd.name, "", ""))
               else:
                   for subnet in subnets:
                       data.append((tenant.name, app.name, bd.name, subnet.addr, subnet.get_scope()))

    # Display the data downloaded
    template = "{0:20} {1:20} {2:20} {3:18} {4:15}"
    print(template.format("Tenant              ", "AppProfile          ", "BridgeDomain        ", "Subnet            ", "Scope          "))
    print(template.format("--------------------", "--------------------", "--------------------", "------------------", "---------------"))
    for rec in data:
        print(template.format(*rec))

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass

実行例

実際の実行例は以下の通りです。common 等、一部の出力は省略しています。「TENANT-2 の BD-2」の Subnet 欄は空欄ですが、これはアドレスが未定義な為であり、意図した通りの正しい表示結果です。

# python aci-show-subnets.py
Tenant               AppProfile           BridgeDomain         Subnet             Scope
-------------------- -------------------- -------------------- ------------------ ---------------
TENANT-1             AP-1                 BD-1                 10.11.1.99/24      private
TENANT-1             AP-1                 BD-2                 10.12.1.99/24      public
TENANT-1             AP-1                 BD-2                 10.12.2.99/24      public
TENANT-1             AP-1                 BD-3                 10.13.1.99/24
TENANT-1             AP-1                 BD-3                 10.13.2.99/24      private,shared
TENANT-1             AP-1                 BD-3                 10.13.3.99/24      public,shared
TENANT-2             AP-1                 BD-1                 10.21.1.99/24      private
TENANT-2             AP-1                 BD-2
TENANT-2             AP-1                 BD-3                 10.23.1.99/24
TENANT-2             AP-1                 BD-3                 10.23.2.99/24      private,shared
TENANT-2             AP-1                 BD-3                 10.23.3.99/24      public,shared