NSX-T の Policy API の「Hierarchical API」で、ネットワークの作成/削除をしてみます。
前回の投稿はこちら。
NSX-T の Policy API をためす。Part.4(Hierarchical API での GET 編)
JSON ファイルの用意。
今回は、これまでの投稿で何度か構築したラボ ネットワーク環境を Hierarchical API で作成してみます。
つぎの一連の投稿で作成したネットワークと、同様のものです。
前提として、前回までに作成/確認したオブジェクトは、ひととおり削除してあります。
自宅ラボで NSX-T 2.5 環境を構築する。Simplified UI 編。Part.1※Web UI で作成。
NSX-T の Policy API をためす。Part.3(オブジェクト作成編)※Policy API での別方法で作成。
まず、前回に Hierarchical API で GET した情報から、
必要な部分のみを残した JSON ファイルを用意しておきます。
NSX-T の Policy API をためす。Part.4(Hierarchical API での GET 編)
JSON ファイルはある程度あつかいやすいように、3つに分けてみました。
より多く分割、もしくは少ない JSON ファイルにまとめることも可能です。
ext-vlan.json ファイルの内容。
{
"resource_type": "Infra",
"id": "infra",
"children": [
{
"Segment": {
"id": "seg-vlan-0200",
"display_name": "seg-vlan-0200",
"type": "DISCONNECTED",
"vlan_ids": [
"200"
],
"transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/4954eeca-decb-487a-8582-b011d60ba19f",
"resource_type": "Segment",
"marked_for_delete": false
},
"resource_type": "ChildSegment",
"marked_for_delete": false
}
]
}
tier0.json ファイルの内容。
{
"resource_type": "Infra",
"id": "infra",
"children": [
{
"Tier0": {
"id": "t0-gw-01",
"display_name": "t0-gw-01",
"ha_mode": "ACTIVE_STANDBY",
"failover_mode": "NON_PREEMPTIVE",
"transit_subnets": [
"100.64.0.0/16"
],
"internal_transit_subnets": [
"169.254.0.0/28"
],
"children": [
{
"LocaleServices": {
"id": "8ad9e401-f41e-4227-8445-36b1092c76a3",
"display_name": "8ad9e401-f41e-4227-8445-36b1092c76a3",
"children": [
{
"Tier0Interface": {
"id": "t0-uplink-01",
"display_name": "t0-uplink-01",
"edge_path": "/infra/sites/default/enforcement-points/default/edge-clusters/a2958967-0579-4cbf-a018-96cfa6553fae/edge-nodes/8e1b5bda-e116-49da-8b4b-bbb2961a7900",
"segment_path": "/infra/segments/seg-vlan-0200",
"type": "EXTERNAL",
"subnets": [
{
"ip_addresses": [
"192.168.200.2"
],
"prefix_len": 24
}
],
"resource_type": "Tier0Interface",
"marked_for_delete": false
},
"resource_type": "ChildTier0Interface",
"marked_for_delete": false
}
],
"resource_type": "LocaleServices",
"marked_for_delete": false
},
"resource_type": "ChildLocaleServices",
"marked_for_delete": false
},
{
"PolicyNat": {
"id": "USER",
"display_name": "USER",
"nat_type": "USER",
"children": [
{
"PolicyNatRule": {
"resource_type": "PolicyNatRule",
"id": "b1a7aa47-e299-4369-a06b-3d10d48e8c68",
"display_name": "t0-snat-01",
"sequence_number": 100,
"action": "SNAT",
"source_network": "172.16.0.0/16",
"service": "",
"translated_network": "192.168.200.2",
"scope": [],
"enabled": true,
"marked_for_delete": false
},
"resource_type": "ChildPolicyNatRule",
"marked_for_delete": false
}
],
"resource_type": "PolicyNat",
"marked_for_delete": false
},
"resource_type": "ChildPolicyNat",
"marked_for_delete": false
},
{
"StaticRoutes": {
"id": "t0-route-01",
"display_name": "t0-route-01",
"network": "0.0.0.0/0",
"next_hops": [
{
"ip_address": "192.168.200.1",
"admin_distance": 1
}
],
"resource_type": "StaticRoutes",
"marked_for_delete": false
},
"resource_type": "ChildStaticRoutes",
"marked_for_delete": false
}
],
"resource_type": "Tier0",
"marked_for_delete": false
},
"resource_type": "ChildTier0",
"marked_for_delete": false
}
]
}
tier1.json ファイルの内容。
{
"resource_type": "Infra",
"id": "infra",
"children": [
{
"PolicyDnsForwarderZone": {
"resource_type": "PolicyDnsForwarderZone",
"id": "dns-zone-01",
"display_name": "dns-zone-01",
"dns_domain_names": [],
"upstream_servers": [
"192.168.1.101",
"192.168.1.102"
],
"marked_for_delete": false
},
"resource_type": "ChildPolicyDnsForwarderZone",
"marked_for_delete": false
},
{
"DhcpServerConfig": {
"id": "dhcp-sv-01",
"display_name": "dhcp-sv-01",
"server_address": "172.16.254.254/24",
"lease_time": 86400,
"resource_type": "DhcpServerConfig",
"marked_for_delete": false
},
"resource_type": "ChildDhcpServerConfig",
"marked_for_delete": false
},
{
"Tier1": {
"id": "t1-gw-01",
"display_name": "t1-gw-01",
"tier0_path": "/infra/tier-0s/t0-gw-01",
"failover_mode": "NON_PREEMPTIVE",
"enable_standby_relocation": false,
"dhcp_config_paths": [
"/infra/dhcp-server-configs/dhcp-sv-01"
],
"route_advertisement_types": [
"TIER1_DNS_FORWARDER_IP",
"TIER1_CONNECTED"
],
"children": [
{
"LocaleServices": {
"id": "96770e38-3e86-4873-bef6-71d60267c957",
"display_name": "96770e38-3e86-4873-bef6-71d60267c957",
"edge_cluster_path": "/infra/sites/default/enforcement-points/default/edge-clusters/a2958967-0579-4cbf-a018-96cfa6553fae",
"preferred_edge_paths": [
"/infra/sites/default/enforcement-points/default/edge-clusters/a2958967-0579-4cbf-a018-96cfa6553fae/edge-nodes/8e1b5bda-e116-49da-8b4b-bbb2961a7900"
],
"resource_type": "LocaleServices",
"marked_for_delete": false
},
"resource_type": "ChildLocaleServices",
"marked_for_delete": false
},
{
"PolicyDnsForwarder": {
"id": "dns-forwarder",
"display_name": "dns-sv-01",
"listener_ip": "172.16.253.254",
"default_forwarder_zone_path": "/infra/dns-forwarder-zones/dns-zone-01",
"resource_type": "PolicyDnsForwarder",
"marked_for_delete": false
},
"resource_type": "ChildPolicyDnsForwarder",
"marked_for_delete": false
}
],
"resource_type": "Tier1",
"marked_for_delete": false
},
"resource_type": "ChildTier1",
"marked_for_delete": false
},
{
"Segment": {
"id": "seg-overlay-01",
"display_name": "seg-overlay-01",
"type": "ROUTED",
"subnets": [
{
"gateway_address": "172.16.1.1/24",
"dhcp_ranges": [
"172.16.1.10-172.16.1.250"
],
"network": "172.16.1.0/24"
}
],
"transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/4d5e3804-e62c-40ab-af7c-99bab2d5e5e8",
"connectivity_path": "/infra/tier-1s/t1-gw-01",
"resource_type": "Segment",
"marked_for_delete": false
},
"resource_type": "ChildSegment",
"marked_for_delete": false
},
{
"Segment": {
"id": "seg-overlay-02",
"display_name": "seg-overlay-02",
"type": "ROUTED",
"subnets": [
{
"gateway_address": "172.16.2.1/24",
"dhcp_ranges": [
"172.16.2.10-172.16.2.250"
],
"network": "172.16.2.0/24"
}
],
"transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/4d5e3804-e62c-40ab-af7c-99bab2d5e5e8",
"connectivity_path": "/infra/tier-1s/t1-gw-01",
"resource_type": "Segment",
"marked_for_delete": false
},
"resource_type": "ChildSegment",
"marked_for_delete": false
}
]
}
ネットワーク環境の作成。
これまでの投稿で紹介したように、API のコールには、Linux クライアントで curl コマンドを利用します。
変数 CREDには「ユーザ名:パスワード」、MGR には NSX Manager のアドレスを格納してあります。
$ MGR=lab-nsxt-mgr-01.go-lab.jp
$ CRED='admin:VMware1!VMware1!'
今回コールする API は、一律でつぎのものです。
対象のオブジェクトとその階層、作成/削除などは、リクエストに渡す JSON データで指定しています。
PATCH /policy/api/v1/infra
それでは、ネットワークを作成していきます。
NSX Manager の UI でも、はじめはオブジェクトがない状態です。
API コールのたびに UI を更新すると、JSON に記載したオブジェクトが作成された様子がわかるはずです。
ext-vlan.json を指定して、境界のネットワークになる、VLAN セグメントを作成。
$ curl -ks -u $CRED -H "Content-Type: application/json" -X PATCH -d @./ext-vlan.jsonhttps://$MGR/policy/api/v1/infra
tier0.json を指定して、Tier-0 ゲートウェイと一連のオブジェクトを作成。
$ curl -ks -u $CRED -H "Content-Type: application/json" -X PATCH -d @./tier0.jsonhttps://$MGR/policy/api/v1/infra
tier1.json を指定して、Tier-1 ゲートウェイと一連のオブジェクトを作成。
$ curl -ks -u $CRED -H "Content-Type: application/json" -X PATCH -d @./tier1.jsonhttps://$MGR/policy/api/v1/infra
ここまでの API コールで、NSX Manager でオブジェクトが作成されました。
ネットワーク環境の削除のための JSON ファイル準備。
以前紹介したように、Policy API では、DELETE メソッドでオブジェクトをひとつずつ削除できます。
NSX-T の Policy API をためす。Part.2(DELETE 編)
Policy API を Hierarchical で利用すると、JSON データの marked_for_delete フラグによるオブジェクト削除もできます。
この場合、環境作成時の JSON ファイルで、削除対象だけ「marked_for_delete: true」とフラグを指定します。
「marked_for_delete: true」を親階層のオブジェクトで指定すると、その配下のオブジェクトも一緒に削除します。
ちなみにこのフラグはデフォルトだと false で、省略可能です。
また、ルート階層の「infra」は削除できません。
今回は、オブジェクト作成時に使用した JSON を「marked_for_delete: true」にした、
~_delete.json ファイルを用意して、オブジェクトを削除します。
それぞれの JSON ファイルで
~_delete.json ファイルを用意して、オブジェクトを削除します。
ext-vlan_delete.json をもとにした ext-vlan_delete.json では、
infra 直下のオブジェクトのみ 「marked_for_delete: true」にしてあります。
(infra オブジェクト自体は削除できないため)
例として、編集のあったファイル末尾の内容だけ、tail コマンドで表示します。
$ tail ./ext-vlan_delete.json
],
"transport_zone_path": "/infra/sites/default/enforcement-points/default/transport-zones/4954eeca-decb-487a-8582-b011d60ba19f",
"resource_type": "Segment",
"marked_for_delete": false
},
"resource_type": "ChildSegment",
"marked_for_delete": true
}
]
}
個人的な JSON ファイル記述方法の工夫として、JSON ファイルでの編集ミス防止箇所のため、
Hierarchical API でオブジェクトの種類を表す「"resource_type": "Child~"」と、
marked_for_delete フラグは、できるだけ各オブジェクトの末尾にセットで記載するようにしています。
tier0.json をもとにした tier0_delete.json も、
Tier0 配下に一連ののオブジェクトが収まる階層構造なので
infra 直下の「ChildTier0」でのみ「marked_for_delete: true」にしてあります。
$ tail ./tier0_delete.json
}
],
"resource_type": "Tier0",
"marked_for_delete": false
},
"resource_type": "ChildTier0",
"marked_for_delete": true
}
]
}
tier1_delete.json は、「Tier0」配下の階層に収まっていないオブジェクトがあり、
複数個所で "marked_for_delete": true の指定が必要になる例です。
階層全体でなく、個々のオブジェクトで marked_for_delete を true にしても削除ができるので、
すこし雑な方法ですが 元の tier1.json ファイルを、sed で一括置換してしまいます。
$ cat ./tier1.json | sed 's/"marked_for_delete": false/"marked_for_delete": true/g' > tier1_delete.json
$ diff ./tier1.json ./tier1_delete.json
15c15
< "marked_for_delete": false
---
> "marked_for_delete": true
18c18
< "marked_for_delete": false
---
> "marked_for_delete": true
27c27
< "marked_for_delete": false
---
> "marked_for_delete": true
30c30
< "marked_for_delete": false
---
> "marked_for_delete": true
56c56
< "marked_for_delete": false
---
> "marked_for_delete": true
59c59
< "marked_for_delete": false
---
> "marked_for_delete": true
68c68
< "marked_for_delete": false
---
> "marked_for_delete": true
71c71
< "marked_for_delete": false
---
> "marked_for_delete": true
75c75
< "marked_for_delete": false
---
> "marked_for_delete": true
78c78
< "marked_for_delete": false
---
> "marked_for_delete": true
97c97
< "marked_for_delete": false
---
> "marked_for_delete": true
100c100
< "marked_for_delete": false
---
> "marked_for_delete": true
119c119
< "marked_for_delete": false
---
> "marked_for_delete": true
122c122
< "marked_for_delete": false
---
> "marked_for_delete": true
ネットワーク環境の削除。
それではオブジェクトを削除します。
今回は、あらかじめオーバーレイ セグメントは VM の vNIC から外して(別のポートグループを割り当てて)おき、
セグメントのポートがすでにない状態から開始しています。
tier1_delete.json を指定して、Tier-1 ゲートウェイと一連のオブジェクトを削除します。
$ curl -ks -u $CRED -H "Content-Type: application/json" -X PATCH -d @./tier1_delete.jsonhttps://$MGR/policy/api/v1/infra
tier0_delete.json を指定して、Tier-0 ゲートウェイと一連のオブジェクトを削除します。
$ curl -ks -u $CRED -H "Content-Type: application/json" -X PATCH -d @./tier0_delete.jsonhttps://$MGR/policy/api/v1/infra
ext-vlan_delete.json を指定して、VLAN セグメントを削除します。
$ curl -ks -u $CRED -H "Content-Type: application/json" -X PATCH -d @./ext-vlan_delete.jsonhttps://$MGR/policy/api/v1/infra
これらの API コールによって、(JSON の内容に問題がなければ)さきほど作成したオブジェクトが削除されます。
処理が完了すると、NSX Manager の Web UI でも、今回の手順開始時と同様にオブジェクト件数がゼロ件になります。
(ブラウザの更新や、「更新」ボタンで画面に反映されるはずです)
オブジェクトの指定によっては、対象オブジェクト同士の参照関係によってエラーになることがありますが、
その場合は少し待つと、(おそらく内部でリトライされて)エラーとなっていたオブジェクトでも削除されたりします。
もしくは、エラーになったオブジェクトを含むコールをリトライすることで、オブジェクトを削除できることがあります。
NSX-T の Policy API を利用する場合は、Hierarchical API 形式にすることで、
オブジェクト同士の参照関係を気にする苦労を削減できます。
手順の簡略化や構成管理の面で Hierarchical API 形式のほうが便利かなと思います。
ちなみに、いまのところのおすすめ資料は下記かなと思います。
NSX Policy API: Getting Started Guide
https://images.nsx.techzone.vmware.com/sites/default/files/PolicyAPI-v1.0.pdf
以上、Policy API の Hierarchical API でオブジェクトを作成/削除してみる話でした。