13. IBM Cloud: VMware as a Service（VMWaaS) - VMware Cloud Director OpenAPIの実行例

# 1. はじめに

今まで色々な作業をVMware Console（VMware Cloud Director)を使って操作してきましたが、作業内容によってはAPIを使った自動化作業を実施したいということもあるでしょう。[前回](https://qiita.com/testnin2/items/3e0e86a25bfd06a165bf)に紹介したAPIはあくまでVMWaaSのAPIであって、VDC networkなどを管理するためのAPIではありません。今回は、VDC内のコンポーネント管理することができる、VMware Cloud Director OpenAPIを呼び出す方法を紹介したいと思います。

- [01. IBM Cloud: VMware as a Service（VMWaaS)の概要](https://qiita.com/testnin2/items/d39ba856f70fc14ea719) 
- [02. IBM Cloud: VMware as a Service（VMWaaS) - VDCの注文](https://qiita.com/testnin2/items/a3630d5a532a6ce48720)
- [03. IBM Cloud: VMware as a Service（VMWaaS) - VDCの追加注文](https://qiita.com/testnin2/items/666a8a03db85f983f56a) 
- [04. IBM Cloud: VMware as a Service（VMWaaS) - 外部接続のためのネットワークとNAT/Firewallを構成する](https://qiita.com/testnin2/items/3575b27c2ec2b6242ee6) 
- [05. IBM Cloud: VMware as a Service（VMWaaS) - RHELをプロビジョニングして疎通確認を行う](https://qiita.com/testnin2/items/56901ef332ee060fcf2f) 
- [06. IBM Cloud: VMware as a Service（VMWaaS) - 検証: IBM Cloud private networkへの通信におけるSNATの必要性](https://qiita.com/testnin2/items/5add312256d1e264e31f)
- [07. IBM Cloud: VMware as a Service（VMWaaS) - 検証: isolated networkとの通信](https://qiita.com/testnin2/items/9bc1b57b9636071b7239)
- [08. IBM Cloud: VMware as a Service（VMWaaS) - 検証: routed network間の通信](https://qiita.com/testnin2/items/fa9426df262368ddc2ef) 
- [09. IBM Cloud: VMware as a Service（VMWaaS) - Data Center Groupの構成](https://qiita.com/testnin2/items/f940550d7564db526531) 
- [10. IBM Cloud: VMware as a Service（VMWaaS) - Distributed Firewallの構成](https://qiita.com/testnin2/items/26dd06d28effbd83ff9e) 
- [11. IBM Cloud: VMware as a Service（VMWaaS) - VDC間のVM/vApp Migration](https://qiita.com/testnin2/items/381c5e6db4fdd7ed64d6)
- [12. IBM Cloud: VMware as a Service（VMWaaS) - VMWaaS APIの実行例](https://qiita.com/testnin2/items/3e0e86a25bfd06a165bf)
- [13. IBM Cloud: VMware as a Service（VMWaaS) - VMware Cloud Director OpenAPIの実行例](https://qiita.com/testnin2/items/420e55a06255d626a471) 
- [14. IBM Cloud: VMware as a Service（VMWaaS) - 検証: VIP切り替えによる高可用性構成の確認（手動切替）](https://qiita.com/testnin2/items/fead2339a999242ecae9) 
- [15. IBM Cloud: VMware as a Service（VMWaaS) - 検証: VIP切り替えによる高可用性構成の確認（keepalived）](https://qiita.com/testnin2/items/2a5c9660ccfab74faa49) 
- [16. IBM Cloud: VMware as a Service（VMWaaS) - Transit Gateway接続](https://qiita.com/testnin2/items/1ec6223b6713eb58e156) 
- [17. IBM Cloud: VMware as a Service（VMWaaS) - Veeam Backup and Replication service連携](https://qiita.com/testnin2/items/69fd29db9f8cc313e353) 

# 2. VMware Cloud Director OpenAPI: API Reference

1. クエスチョンマークのボタンを押下して、`API Explorer`を選択。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/1be771b4-5e2c-f8e5-b6a3-862f80508649.png)
2. このページで紹介されているAPI一覧を使えば良いことがわかる。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/6df1105e-1570-ab4f-4f74-abcc57d22c56.png)
3. 例えば、VDCのnetwork一覧を呼び出すためには、`orgVdcNetworks`に移動し、`Try it out`を実行する。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/4631ebdd-d676-94a6-d892-14a4debd0bcd.png)
4. pageやpagesizeなどの値はデフォルトのまま、Executeを実行。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/287cc5e9-147f-d0dd-b582-2da0aa9268db.png)
5. 以下の結果が得られる。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/a3aed36e-a96a-bd00-f4ad-6b5fc7a5c181.png)

以上により、VMware Cloud Director OpenAPIの呼び出し方は分かりました。しかし、その際のAccess Token（`Bearer`以下の箇所）が不明です。まさかAPIを実行する度に、コンソールアクセスしてAccess Tokenを取得するなんてことはできませんからね。。。


# 3. Access Tokenの生成方法

VMware Cloud Director OpenAPIのAccess Tokenの取得方法は、[Generate an API Access Token](https://docs.vmware.com/en/VMware-Cloud-Director/10.4/VMware-Cloud-Director-Tenant-Portal-Guide/GUID-A1B3B2FA-7B2C-4EE1-9D1B-188BE703EEDE.html?hWord=N4IghgNiBcIIIAUCSACALgewNYFMB2IAvkA)が参考になります。要は、

- UI上からAPI Token(=Refresh Token)を生成し、手元に保管しておく。このRefresh Tokenの有効期限はない。
- このRefresh TokenからAccess Tokenを生成する。

という手順を踏みます。以下、実際に作業をしてみます。

1. User preferencesを選択![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/0178147c-d38e-4f69-111c-127c5710598d.png)
2. API Tokensにて`NEW`を押下。このAPI TokenがRefresh Tokenです。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/b5e578dc-6b79-1118-d65b-b6c6241df3cd.png)
3. API Token名を入力して`CREATE`。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/3e50be98-c3de-b0f8-19c3-a6b70c8df2bb.png)
4. API Token(Refresh Token)が生成された。この情報は二度と参照することができない。今回は以下のように`ibmcloud_vmwaas_apitoken`というファイルに控えておく。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/8d1185d0-5228-f9b5-9fcc-6d501063cce0.png)

```txt:ibmcloud_vmwaas_apitoken
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

この情報を使って、Access Tokenを得ることができます。

```txt:organization_nameは自身のものに変更してください。
$ vmwaas_apitoken=$(cat ibmcloud_vmwaas_apitoken)
$ organization_name="8ed285a1-b804-4f6c-bad7-783b25605194"

$ curl -sX POST "https://dirw082.us-south.vmware.cloud.ibm.com/oauth/tenant/${organization_name}/token" -H 'Accept: application/json' -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=refresh_token&refresh_token=${vmwaas_apitoken}" | jq
{
  "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
```

以上により、アクセストークンを取得できたことを確認できました。


# 4. 再度API Explorerで参照したAPIを実行してみる。


```txt:organization_nameは自身のものに変更してください。
$ vmwaas_apitoken=$(cat ibmcloud_vmwaas_apitoken)
$ organization_name="8ed285a1-b804-4f6c-bad7-783b25605194"

$ vmwaas_accesstoken=$(curl -sX POST "https://dirw082.us-south.vmware.cloud.ibm.com/oauth/tenant/${organization_name}/token" -H 'Accept: application/json' -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=refresh_token&refresh_token=${vmwaas_apitoken}"  | jq -r '.access_token')

$ curl -sX GET "https://dirw082.us-south.vmware.cloud.ibm.com/cloudapi/1.0.0/orgVdcNetworks?page=1&pageSize=16" -H "accept: application/json;version=37.1" -H "Authorization: Bearer ${vmwaas_accesstoken}" | jq
{
  "resultTotal": 3,
  "pageCount": 1,
  "page": 1,
  "pageSize": 16,
  "associations": null,
  "values": [
    {
      "id": "urn:vcloud:network:549a62bc-8553-492f-ad8f-6524f9a9c448",
      "name": "nw1-isolated-vdc01",
      "description": "",
      "subnets": {
        "values": [
          {
            "gateway": "192.168.102.1",
            "prefixLength": 24,
            "dnsSuffix": null,
            "dnsServer1": "161.26.0.10",
            "dnsServer2": "161.26.0.11",
            "ipRanges": {
              "values": [
                {
                  "startAddress": "192.168.102.2",
                  "endAddress": "192.168.102.99"
                }
              ]
            },
            "enabled": true,
            "totalIpCount": 98,
            "usedIpCount": 0
          }
        ]
      },
      "backingNetworkId": null,
      "backingNetworkType": "NSXT_FLEXIBLE_SEGMENT",
      "parentNetworkId": null,
      "networkType": "ISOLATED",
      "orgVdc": {
        "name": "mt-vdc01",
        "id": "urn:vcloud:vdc:686d5f0d-1af2-4b5d-9262-1c4b3081799a"
      },
      "ownerRef": {
        "name": "mt-vdc01",
        "id": "urn:vcloud:vdc:686d5f0d-1af2-4b5d-9262-1c4b3081799a"
      },
      "orgVdcIsNsxTBacked": null,
      "orgRef": {
        "name": "8ed285a1-b804-4f6c-bad7-783b25605194",
        "id": "urn:vcloud:org:41860b51-a949-4e2b-a21c-ba9128fe5853"
      },
      "connection": null,
      "isDefaultNetwork": null,
      "shared": false,
      "enableDualSubnetNetwork": false,
      "status": "REALIZED",
      "lastTaskFailureMessage": null,
      "guestVlanTaggingAllowed": false,
      "retainNicResources": false,
      "crossVdcNetworkId": null,
      "crossVdcNetworkLocationId": null,
      "overlayId": null,
      "totalIpCount": 98,
      "usedIpCount": 0,
      "routeAdvertised": false,
      "securityGroups": null,
      "segmentProfileTemplateRef": null
    },
    {
      "id": "urn:vcloud:network:b1ded7f0-bd5b-48ed-be59-9e0415cfb738",
      "name": "nw1-routed-vdc01",
      "description": "",
      "subnets": {
        "values": [
          {
            "gateway": "192.168.100.1",
            "prefixLength": 24,
            "dnsSuffix": "",
            "dnsServer1": "161.26.0.10",
            "dnsServer2": "161.26.0.11",
            "ipRanges": {
              "values": [
                {
                  "startAddress": "192.168.100.2",
                  "endAddress": "192.168.100.99"
                }
              ]
            },
            "enabled": true,
            "totalIpCount": 98,
            "usedIpCount": 1
          }
        ]
      },
      "backingNetworkId": null,
      "backingNetworkType": "NSXT_FLEXIBLE_SEGMENT",
      "parentNetworkId": null,
      "networkType": "NAT_ROUTED",
      "orgVdc": null,
      "ownerRef": {
        "name": "DAL-VDC-GROUP1",
        "id": "urn:vcloud:vdcGroup:895fa195-890e-4e4d-b85f-0cb8097c6cf0"
      },
      "orgVdcIsNsxTBacked": null,
      "orgRef": {
        "name": "8ed285a1-b804-4f6c-bad7-783b25605194",
        "id": "urn:vcloud:org:41860b51-a949-4e2b-a21c-ba9128fe5853"
      },
      "connection": {
        "routerRef": {
          "name": "mt-vdc01-e116ab26-3f47-43f9-8cf6-05",
          "id": "urn:vcloud:gateway:1225668b-e935-407b-8190-645a3f24d628"
        },
        "connectionType": "INTERNAL",
        "connectionTypeValue": "INTERNAL",
        "connected": true
      },
      "isDefaultNetwork": null,
      "shared": true,
      "enableDualSubnetNetwork": false,
      "status": "REALIZED",
      "lastTaskFailureMessage": null,
      "guestVlanTaggingAllowed": false,
      "retainNicResources": false,
      "crossVdcNetworkId": null,
      "crossVdcNetworkLocationId": null,
      "overlayId": null,
      "totalIpCount": 98,
      "usedIpCount": 1,
      "routeAdvertised": false,
      "securityGroups": null,
      "segmentProfileTemplateRef": null
    },
    {
      "id": "urn:vcloud:network:6b2b9879-6236-464e-ae9e-d0bfe2dcf519",
      "name": "nw2-routed-vdc01",
      "description": "",
      "subnets": {
        "values": [
          {
            "gateway": "192.168.101.1",
            "prefixLength": 24,
            "dnsSuffix": "",
            "dnsServer1": "161.26.0.10",
            "dnsServer2": "161.26.0.11",
            "ipRanges": {
              "values": [
                {
                  "startAddress": "192.168.101.2",
                  "endAddress": "192.168.101.99"
                }
              ]
            },
            "enabled": true,
            "totalIpCount": 98,
            "usedIpCount": 1
          }
        ]
      },
      "backingNetworkId": null,
      "backingNetworkType": "NSXT_FLEXIBLE_SEGMENT",
      "parentNetworkId": null,
      "networkType": "NAT_ROUTED",
      "orgVdc": null,
      "ownerRef": {
        "name": "DAL-VDC-GROUP1",
        "id": "urn:vcloud:vdcGroup:895fa195-890e-4e4d-b85f-0cb8097c6cf0"
      },
      "orgVdcIsNsxTBacked": null,
      "orgRef": {
        "name": "8ed285a1-b804-4f6c-bad7-783b25605194",
        "id": "urn:vcloud:org:41860b51-a949-4e2b-a21c-ba9128fe5853"
      },
      "connection": {
        "routerRef": {
          "name": "mt-vdc01-e116ab26-3f47-43f9-8cf6-05",
          "id": "urn:vcloud:gateway:1225668b-e935-407b-8190-645a3f24d628"
        },
        "connectionType": "INTERNAL",
        "connectionTypeValue": "INTERNAL",
        "connected": true
      },
      "isDefaultNetwork": null,
      "shared": true,
      "enableDualSubnetNetwork": false,
      "status": "REALIZED",
      "lastTaskFailureMessage": null,
      "guestVlanTaggingAllowed": false,
      "retainNicResources": false,
      "crossVdcNetworkId": null,
      "crossVdcNetworkLocationId": null,
      "overlayId": null,
      "totalIpCount": 98,
      "usedIpCount": 1,
      "routeAdvertised": false,
      "securityGroups": null,
      "segmentProfileTemplateRef": null
    }
  ]
}
```