Virtual Infrastructure JSON API(VI/JSON API)の触り方

はじめに

前回のエントリ で、vSphere に古くから実装されている API である vSphere Web Services API(SOAP API)の触り方を紹介しました。その中で、Virtual Infrastructure JSON API にひとことだけ触れています。

SOAP API を(広義の)REST API のように触れる Virtual Infrastructure JSON API も vCenter Server 8.0 U1 以降が必要で、まだまだ一般的ではありません。

vSphere Web Services API(SOAP API)の触り方 | kurokobo.com

Virtual Infrastructure JSON API(VI/JSON API)は、vCenter Server 8.0 U1 で追加された新しい API で、ひとことで雑に表現するなら、従来の SOAP API の REST API 版 です。

本エントリでは、まだ日本語ではほとんど情報がないこの新しい API について、実例とともに簡単に紹介します。

なお、vSphere の REST API といえば vSphere Automation API が一般的ですが、VI/JSON API はこれとはまったく別物 です。

基本的な考え方

概要

Virtual Infrastructure JSON API(VI/JSON API)は、前述の通り、ひとことでは 従来の SOAP API の REST API 版 で、次の特徴を持ちます。

  • SOAP API と同じエンドポイントを利用する
  • SOAP API と同じ API が公開されている(後方互換性がある)
  • XML ではなく JSON でやりとりする
  • Cookie ではなく専用の HTTP ヘッダで認証する
  • 管理対象オブジェクトのプロパティを直接参照できる(新機能、後述)

SOAP API と後方互換性がある ように設計されているため、従来の SOAP API を利用したクライアントが、ロジックを維持したまま REST API での操作に移行 する目的で利用できます。ただしこの場合は、お作法が REST API に変わるだけで、実行すべきメソッドやその順序、結果から拾うべき値などが SOAP API のときと変わるわけではない点には注意が必要です。この意味で、従来の SOAP API の操作に習熟することは、VI/JSON API を触る上でも重要です。

一方で、後述の実例で紹介しますが、管理対象オブジェクトのプロパティの取得PropertyCollector を使わずに直接 GET できる 点など、後発ならではの機能強化もされており、この点は VI/JSON API の明らかな強みと言えます。

実行イメージ

VI/JSON API の操作感は非常にシンプルで、雑にいうとイマドキです。

例えば、SOAP API で仮想マシンの電源を入れる 操作をしたい場合、VirtualMachine オブジェクトの PowerOnVM_Task を実行 するため、curl では次のコマンドが必要でした(認証済みかつ管理対象オブジェクト ID は特定済みのものとしています)。

$ WSAPI_URL=https://kuro-vcs01.kurokobo.internal/sdk
$ curl \
  -sX POST ${WSAPI_URL} \
  -b ./cookies.txt \
  -H 'content-type: text/xml; charset="utf-8"' \
  -H 'soapaction: urn:vim25/8.0.2.0' \
  -d @- << EOF
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <PowerOnVM_Task xmlns="urn:vim25">
      <_this type="VirtualMachine">vm-14011</_this>
    </PowerOnVM_Task>
  </Body>
</Envelope>
EOF

同じ VirtualMachine オブジェクトの PowerOnVM_Task の実行 を、今度は VI/JSON API で行う 場合、コマンドは次の通りです。この操作ではリクエストボディは空 です。

$ JSONAPI_URL=https://kuro-vcs01.kurokobo.internal/sdk/vim25/8.0.2.0/VirtualMachine/vm-14011/PowerOnVM_Task
$ curl \
  -sX POST ${JSONAPI_URL} \
  -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}"

両者を見比べると、与えているパラメータは同じ ですが、指定方法が異なっている ことが読み取れます。

  • リクエストボディの XML で指定していた 操作対象やメソッド名URL で指定
    • VirtualMachinevm-14011PowerOnVM_Task
  • リクエストヘッダで渡していたバージョン情報も URL で指定
    • 8.0.2.0
  • Cookie で渡していた 認証情報リクエストヘッダで指定
    • vmware-api-session-id

公式ドキュメント

Virtual Infrastructure JSON API に関する公式のドキュメントとして、リファレンスのほか、前回のエントリ でも紹介したプログラミングガイドの中に、8.0 U1 以降は VI/JSON API についての章が追加されています。

また、VI/JSON API が実装された当初、VMWARE {code} の公式ブログ でも紹介されていました。概要から実例まで紹介されており、併せて参考にできます。

参考: リクエスト URL の組み立て

VI/JSON API では、操作したい管理対象オブジェクトと実行したいメソッドは、URL で指定します。ガイドでも紹介 されていますが、構文は次の通りです。

  • https://[FQDN]/sdk/vim25/[バージョン]/[型]/[管理対象オブジェクト ID]/[メソッド]

これは、SOAP API の HTTP リクエスト中のそれぞれ以下に対応します。

POST /sdk HTTP/2
...
soapaction: urn:vim25/[バージョン]
...

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <[メソッド] xmlns="urn:vim25">
      <_this type="[型]">[管理対象オブジェクト ID]</_this>
    </[メソッド]>
    ...
  </Body>
</Envelope>

参考: リクエストボディの組み立て

VI/JSON API では、メソッドに渡すパラメータをリクエストボディに JSON 形式で含めます。ガイドでも紹介 されています。

{
  "<パラメータ名>": <値>
}

ただし、値が SOAP API の WSDL で定義されている型のオブジェクトの場合、都度 _typeName キーで型名を明示します。

例えば、PropertyFilterSpec 型のプロパティ propSet は、XML では次のように組み立てられます。

<propSet>
  <type>VirtualMachine</type>
  <pathSet>name</pathSet>
</propSet>

これを JSON で表すと次のようになります。リファレンス からプロパティ propSet が PropertySpec 型のオブジェクトの配列であることがわかるため、配列 [] とし、_typeNamePropertySpec を与えます。

{
  "propSet": [
    {
      "_typeName": "PropertySpec",
      "type": "VirtualMachine", 
      "pathSet": ["name"]
    }
  ]
}

すべてのオブジェクトを XML から JSON に手で書き換えていくのは非常に大変です。このため、リファレンスのオブジェクトやメソッドごとのページでも JSON の例が示されている ほか、XML と JSON を相互変換する Transcoder API も用意されています。Transcoder API の使い方は本エントリの末尾で紹介しています。

本エントリで紹介する実例

VI/JSON API を操作する実例として、前回のエントリ で紹介したシナリオのうち、仮想マシンの設定の取得 を取り上げます。ただし、VI/SOAP API の特性から、このシナリオは次の二つのパタンで実現できるため、それぞれ紹介します。

  • 従来の SOAP API の操作をそのまま VI/JSON API に置き換える場合
  • VI/JSON API のネイティブの方法を使う場合

いずれにせよ、認証してセッションを作成する操作対象の管理対象オブジェクト ID を特定する操作 は必須のため、まずはこれを行います。

なお、以降の全ての例で次の変数は共通です。

$ JSONAPI_HOST="kuro-vcs01.kurokobo.internal"
$ JSONAPI_RELEASE="8.0.2.0"

前提 (1): 認証とセッションの作成

認証には SOAP API のときと同様に SessionManager の Login を実行しますが、まずは SessionManager の特定が必要です。

SOAP API の手法に従う場合、ServiceInstance の RetrieveServiceContent に POST して確認します。

$ JSONAPI_SI_MOID="ServiceInstance"
$ JSONAPI_SM_MOID=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
  | jq -r .sessionManager.value \
  | xargs -t0 \
)
$ echo "${JSONAPI_SM_MOID}"
SessionManager

VI/JSON API ネイティブの方法として、ServiceInstance の content を GET することでも同様の結果が得られます。

$ JSONAPI_SI_MOID="ServiceInstance"
$ JSONAPI_SM_MOID=$( \
  curl \
    -sX GET \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/content \
  | jq -r .sessionManager.value \
  | xargs -t0 \
)
$ echo "${JSONAPI_SM_MOID}"
SessionManager

特定できた SessionManager の ID を URL で指定して、Login を実行します。レスポンスヘッダで vmware-api-session-id が返ってくるため、後続の操作に備えてこの値を保存します。

$ JSONAPI_USERNAME="wsapi@vsphere.local"
$ JSONAPI_PASSWORD="VMware123!"
$ JSONAPI_LOCALE="en_US"
$ JSONAPI_SESSION_ID=$( \
  curl \
    -siX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/SessionManager/${JSONAPI_SM_MOID}/Login \
    -H "content-type: application/json" \
    -d @- << EOF \
  | grep "vmware-api-session-id" | tr -d "\r" | cut -d " " -f 2 \
  | xargs -t0
{
  "userName": "${JSONAPI_USERNAME}",
  "password": "${JSONAPI_PASSWORD}",
  "locale": "${JSONAPI_LOCALE}"
}
EOF
)
$ echo "${JSONAPI_SESSION_ID}"
61c2623dfc43bf7dc910205a57b50db9cb19a195

なお、ヘッダ vmware-api-session-id は VI/JSON API ではなく vSphere Automation API(いわゆる REST API)でも利用していますが、セッション ID は API ごとに独立しているため、使いまわしはできません。

前提 (2): 操作する管理対象オブジェクトの特定

この流れは SOAP API のときと同様です。今回も仮想マシン kuro-exec01 の管理対象オブジェクト ID を調べるものとします。

まずは ViewManager の CreateContainerView で ContainerView を作成します。

# ViewManager の ID の特定
$ JSONAPI_VIEWMANAGER_MOID=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
  | jq -r .viewManager.value \
  | xargs -t0 \
)
$ echo "${JSONAPI_VIEWMANAGER_MOID}"
ViewManager

# インベントリのルートフォルダの特定
$ JSONAPI_ROOT_FOLDER=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
  | jq -r .rootFolder \
  | xargs -t0 \
)
$ echo "${JSONAPI_ROOT_FOLDER}"
{
  "_typeName": "ManagedObjectReference",
  "value": "group-d1",
  "type": "Folder"
}

# ContainerView の作成
$ JSONAPI_CONTAINER_VIEW=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ViewManager/${JSONAPI_VIEWMANAGER_MOID}/CreateContainerView \
    -H "content-type: application/json" \
    -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
    -d @- << EOF \
    | xargs -t0
{
  "container": ${JSONAPI_ROOT_FOLDER},
  "recursive": true,
  "type": ["VirtualMachine"]
}
EOF
)
$ echo "${JSONAPI_CONTAINER_VIEW}"
{
    "_typeName": "ManagedObjectReference", 
    "value": "session[5270677a-f371-0117-7df3-36c881fd1118]525d75e8-2e95-3187-449f-41bc9c47f780", 
    "type": "ContainerView"
}

PropertyCollector の RetrievePropertiesEx を使用して仮想マシンの管理対象オブジェクト ID と名前の一覧を取得し、目的の仮想マシン kuro-exec01 の管理対象オブジェクト ID を特定します。以下の例では、レスポンスの JSON の中身をそのまま jq に渡して、jq の中で仮想マシンを検索しています。

# PropertyCollector の ID の特定
$ JSONAPI_PROPERTYCOLLECTOR_MOID=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
  | jq -r .propertyCollector.value \
  | xargs -t0 \
)
$ echo "${JSONAPI_PROPERTYCOLLECTOR_MOID}"
propertyCollector

# 仮想マシンの ID と名前の一覧の取得
$ JSONAPI_TARGET_VM="kuro-exec01"
$ JSONAPI_VM_MOID=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/PropertyCollector/${JSONAPI_PROPERTYCOLLECTOR_MOID}/RetrievePropertiesEx \
    -H "content-type: application/json" \
    -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
    -d @- << EOF \
  | jq -r --arg VM "${JSONAPI_TARGET_VM}" '.objects[] | select (.propSet[].val._value == $VM) | .obj.value'
{
  "specSet": [
    {
      "_typeName": "PropertyFilterSpec", 
      "propSet": [
        {
          "_typeName": "PropertySpec", 
          "type": "VirtualMachine", 
          "pathSet": ["name"]
        }
      ], 
      "objectSet": [
        {
          "_typeName": "ObjectSpec", 
          "obj": ${JSONAPI_CONTAINER_VIEW}, 
          "skip": true, 
          "selectSet": [
            {
              "_typeName": "TraversalSpec", 
              "type": "ContainerView", 
              "path": "view"
            }
          ]
        }
      ]
    }
  ],
  "options": {
    "_typeName": "RetrieveOptions", 
    "maxObjects": 1000
  }
}
EOF
)
$ echo "${JSONAPI_VM_MOID}"
vm-14011

使い終わった ContainerView は、ContainerView の DestroyView で削除します。

$ JSONAPI_CONTAINER_VIEW_MOID_ENCODED=$(echo "${JSONAPI_CONTAINER_VIEW}" | jq -r ".value | @uri")
$ curl \
  -sX POST \
  https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ContainerView/${JSONAPI_CONTAINER_VIEW_MOID_ENCODED}/DestroyView \
  -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}"

実例: 仮想マシンの設定を取得する(SOAP API 互換)

仮想マシンの設定のうち vmOpNotificationTimeout の値を確認したいものとして、まずは従来の SOAP API を置き換える場合の実例です。

この場合は、PropertyCollector の RetrievePropertiesEx を利用します。

$ JSONAPI_VM_OP_NOTIFICATION_TIMEOUT=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/PropertyCollector/${JSONAPI_PROPERTYCOLLECTOR_MOID}/RetrievePropertiesEx \
    -H "content-type: application/json" \
    -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
    -d @- << EOF \
  | jq -r .objects[].propSet[].val.vmOpNotificationTimeout
{
  "specSet": [
    {
      "_typeName": "PropertyFilterSpec",
      "propSet": [
        {
          "_typeName": "PropertySpec",
          "type": "VirtualMachine", 
          "pathSet": ["config"]
        }
      ],
      "objectSet": [
        {
          "_typeName": "ObjectSpec",
          "obj": {
            "_typeName": "ManagedObjectReference",
            "value": "${JSONAPI_VM_MOID}",
            "type": "VirtualMachine"
          },
          "skip": false
        }
      ]
    }
  ],
  "options": {
    "_typeName": "RetrieveOptions"
  }
}
EOF
)
$ echo "${JSONAPI_VM_OP_NOTIFICATION_TIMEOUT}"
300

実例: 仮想マシンの設定を取得する(VI/JSON API ネイティブ)

同じ設定を VI/JSON API ネイティブの方法で確認する場合、VirtualMachine の config を GET するだけです。

$ JSONAPI_VM_OP_NOTIFICATION_TIMEOUT=$( \
  curl \
    -sX GET \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/VirtualMachine/${JSONAPI_VM_MOID}/config \
    -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
  | jq -r .vmOpNotificationTimeout
)
$ echo "${JSONAPI_VM_OP_NOTIFICATION_TIMEOUT}"
300

補足: XML と JSON の相互変換

SOAP API を VI/JSON API に置き換えていく際、XML を JSON に書き換えたり、逆に JSON を XML に書き換えたりする必要が生じます。

この目的で、オブジェクトの XML と JSON を相互に変換できる Transcoder API が 8.0 U2 で実装されました。

例えば、SOAP API の PropertyCollector オブジェクトの RetrievePropertiesEx メソッド には、パラメータ specSet として PropertyFilterSpec 型のオブジェクトを渡していました。XML では、次のハイライト部分(7-18 行)です。

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <RetrievePropertiesEx xmlns="urn:vim25">
      <_this type="PropertyCollector">propertyCollector</_this>
      <specSet>
        <propSet>
          <type>VirtualMachine</type>
          <pathSet>name</pathSet>
        </propSet>
        <objectSet>
          <obj type="ContainerView">session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4</obj>
          <skip>true</skip>
          <selectSet xmlns:XMLSchema-instance="http://www.w3.org/2001/XMLSchema-instance" XMLSchema-instance:type="TraversalSpec">
            <type>ContainerView</type>
            <path>view</path>
          </selectSet>
        </objectSet>
      </specSet>
      <options>
        <maxObjects>1000</maxObjects>
      </options>
    </RetrievePropertiesEx>
  </Body>
</Envelope>

この specSet を Transcoder API で JSON に変換したいときは、次のリクエストを実行します。変換の方向をヘッダ content-typeaccept で指定し、リクエストボディとして変換したい文字列を渡しています。変換元の型名は xsi:type で明示します。レスポンスで変換された JSON 文字列が返ってきます。

$ JSONAPI_SPECSET_JSON=$( \
  curl \
    -sX POST \
  https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/transcoder \
    -H 'content-type: application/xml' \
    -H 'accept: application/json' \
    -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
    -d @- << EOF
<obj versionId="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:vim25" xsi:type="PropertyFilterSpec">
  <propSet>
    <type>VirtualMachine</type>
    <pathSet>name</pathSet>
  </propSet>
  <objectSet>
    <obj type="ContainerView">session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4</obj>
    <skip>true</skip>
    <selectSet xmlns:XMLSchema-instance="http://www.w3.org/2001/XMLSchema-instance" XMLSchema-instance:type="TraversalSpec">
      <type>ContainerView</type>
      <path>view</path>
    </selectSet>
  </objectSet>
</obj>
EOF
)

$ echo "${JSONAPI_SPECSET_JSON}"
{
    "_typeName": "PropertyFilterSpec", 
    "propSet": [
        {
            "_typeName": "PropertySpec", 
            "type": "VirtualMachine", 
            "pathSet": ["name"]
        }
    ], 
    "objectSet": [
        {
            "_typeName": "ObjectSpec", 
            "obj": {
                "_typeName": "ManagedObjectReference", 
                "value": "session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4", 
                "type": "ContainerView"
            }, 
            "skip": true, 
            "selectSet": [
                {
                    "_typeName": "TraversalSpec", 
                    "type": "ContainerView", 
                    "path": "view"
                }
            ]
        }
    ]
}

逆に JSON を変換して XML にもできます。例として、上の例で返ってきた JSON をそのまま渡して XML にします(変換の方向が逆なので、content-typeaccept の値を入れ替えています)。

$ JSONAPI_SPECSET_XML=$( \
  curl \
    -sX POST \
    https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/transcoder \
    -H "content-type: application/json" \
    -H 'accept: application/xml' \
    -H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
    -d @- << EOF
{
    "_typeName": "PropertyFilterSpec", 
    "propSet": [
        {
            "_typeName": "PropertySpec", 
            "type": "VirtualMachine", 
            "pathSet": ["name"]
        }
    ], 
    "objectSet": [
        {
            "_typeName": "ObjectSpec", 
            "obj": {
                "_typeName": "ManagedObjectReference", 
                "value": "session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4", 
                "type": "ContainerView"
            }, 
            "skip": true, 
            "selectSet": [
                {
                    "_typeName": "TraversalSpec", 
                    "type": "ContainerView", 
                    "path": "view"
                }
            ]
        }
    ]
}
EOF
)

$ echo "${JSONAPI_SPECSET_XML}" | xmllint --format -
<?xml version="1.0"?>
<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="8.0.2.0" xsi:type="PropertyFilterSpec">
  <propSet>
    <type>VirtualMachine</type>
    <pathSet>name</pathSet>
  </propSet>
  <objectSet>
    <obj type="ContainerView">session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4</obj>
    <skip>true</skip>
    <selectSet xsi:type="TraversalSpec">
      <type>ContainerView</type>
      <path>view</path>
    </selectSet>
  </objectSet>
</obj>

なお、Transcoder API の利用にはコマンド例のとおり認証が必要ですが、SOAP API クライアントからの利用をしやすくするため、Transcoder API だけは SOAP API と同じ Cookie を利用した認証も許容されているようです。

補足: curl でヘッダを取り出すときの考慮点

curl に限定した余談です。

curl でレスポンスヘッダから値を拾うとき、-v-I でヘッダを標準出力に吐かせてから grep するパタンがよく使われますが、このとき、curl はサーバと送受信したヘッダをそのまま出力するようです。つまり、行末が CR+LF になっています。

# レスポンスヘッダの content-type を拾う例
$ curl -sI --no-styled-output www.example.com \
  | grep -i --color=never content-type
Content-Type: text/html; charset=UTF-8

# バイナリダンプすると行末に CR+LF(0x0d, 0x0a)があることがわかる
$ curl -sI --no-styled-output www.example.com \
  | grep -i --color=never content-type \
  | od -tx1z -Ax
000000 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65  >Content-Type: te<
000010 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 65 74  >xt/html; charset<
000020 3d 55 54 46 2d 38 0d 0a                          >=UTF-8..<
000028

このため、grep 後に単純に cutawk で雑に値部分を抽出すると、行末の CR も含まれてしまいます。

# awk で値部分を取り出して格納
$ HEADER=$( \
  curl -sI --no-styled-output www.example.com \
  | grep -i --color=never content-type \
  | awk -F ': ' '{print $2}' \
)

# それっぽい切り出しができていそうに見える
$ echo "${HEADER}"
text/html; charset=UTF-8

# 実際には末尾に CR(0x0d)が残っている
$ echo -n "${HEADER}" | od -tx1z -Ax
000000 74 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73  >text/html; chars<
000010 65 74 3d 55 54 46 2d 38 0d                       >et=UTF-8.<
000019

使途次第では無視できますが、少なくとも VI/JSON API では、ヘッダに埋め込むセッション ID の末尾に CR が残った状態でリクエストしても正常に処理されず、レスポンスが得られません。

このため、本エントリのコマンド例では、セッション ID を取り出すコマンドの grep のあとに tr -d "\r" を入れて、CR を明示的に取り除いています。

# CR を取り除く
$ HEADER=$( \
  curl -sI --no-styled-output www.example.com \
  | grep -i --color=never content-type \
  | tr -d "\r" \
  | awk -F ': ' '{print $2}' \
)

# 末尾の CR がなくなる
$ echo -n "${HEADER}" | od -tx1z -Ax
000000 74 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73  >text/html; chars<
000010 65 74 3d 55 54 46 2d 38                          >et=UTF-8<
000018

おわりに

VI/JSON API は、従来の SOAP API のクライアントを REST API ベースの実装に移行できるだけでなく、PropertyCollector を介さずに直接 GET できるオブジェクトが多数用意されており、少なくとも XML と格闘するよりは圧倒的に直感的に操作できます。

vCenter Server 8.0 U1 以降が必要にはなりますが、SOAP API の操作にハードルを感じている場合、VI/JSON API がよい代替手段となりそうです。

利用できるメソッドはリファレンスで一覧 できるので、おもしろそうなものをとにかく触ってみるのもたのしそうです。

@kurokobo

くろいです。ギターアンサンブルやら音響やらがフィールドの IT やさんなアルトギター弾き。たまこう 48 期ぎたさん、SFC '07 おんぞう、新日本ギターアンサンブル、Rubinetto。今は野良気味。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です