読者です 読者をやめる 読者になる 読者になる

らくがきちょう

なんとなく

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

ACI Cisco Network Python SDN

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