2017年10月24日火曜日

vSphereのREST APIを使ってみる

今回はvSphereに6.5からRESTful APIが実装されていたようなので使ってみようと思います。Postmanという試験用のツールから使ってみて使い勝手を把握したら、Pythonから呼び出してみます。RESTなので、別にほかの言語でも構わないですが今更Perlという感じでもないので・・・。
なお、Postmanについては、下記のドキュメントを参考にさせていただきました。あくまで試験用のツールでパスワードなども平文で表示されてしまいますので、試験用途以外では使えないと思います。
Getting Started with the vSphere Automation SDK for REST

今回、使用した環境は下記のとおりです。

  • vCenter Server Appliance 6.5
  • Postman v5.3.1
  • Python 3.5

1 vSphereにユーザを追加します。

vSphereに管理者権限でログインします。
[メニュー]から[管理]を選択し、[ユーザおよびグループ]を選択します。
[+Add]アイコンをクリックし[ユーザ名]、[パスワード]を入力し[OK]をクリックします。

[グローバル権限]をクリックし、[+]アイコンをクリックします。
ユーザに先ほど作成した"test_user"を入力し、"システム管理者"の権限を割り当て[子へ伝達]のチェックを入れ[OK]をクリックします。
# 運用環境では必要なアクセス権に制限した方がいいと思います。


2 Postmanをインストールし起動します。

アカウントを作るように求められますので、アカウントを作成します。
Googleのアカウントも使うことができますので、好きな方を選択します。

3 証明書のエラーチェックを外します。

vCenterは自己署名証明書ですので証明書のチェックをしないように設定します。証明書を買っている場合や組織で用意したものを使用している場合は、下記の手順は不要です。
[File]から[Settings]を選択します。
[General]タブで"SSL certificate verification"を"OFF"に変更します。


4 gitからサンプルをcloneします。

git clone https://github.com/vmware/vsphere-automation-sdk-rest


5 cloneしたサンプルをPostmanにインポートします。

PostmanのGUIから[Import]をクリックし、[Choose files]をクリックします。

.\vsphere-automation-sdk-rest\samples\postman
上記のフォルダから下記4項目を選択し、[開く]をクリックします。
  • vSphere-Automation-Rest-API-Appliance-Resources.postman.json
  • vSphere-Automation-Rest-API-Resources.postman.json
  • vSphere-Automation-Rest-API-Samples.postman.json
  • vSphere-Automation-REST-resources-for-Content-Library.postman_collection.json


6 環境変数を定義します。

右上のアイコンから、[設定]アイコンをクリックし[Manage Environments]を選択します。
[Add]をクリックし、下記の内容を入力し[Add]をクリックし"X"で閉じます。
名前 test_env
vc vCenterのIPもしくはFQDN
user test_user@vsphere.local
password 試験ですので適当に
userをlocalに作成した場合は、@vsphere.localをつけ忘れないようにしてください。

右上のNo Enviromentをクリックして、"test_env"を選択します。


7 ログイン

先程インポートしたPostmanの[Collection]から[vSphere Automation REST Resources]を選択し
[Authentication] - [Login]を選択します。
TYPEに"Basic Auth"を選択し[Send]ボタンをクリックします。
値としてvalueが返ってくればOKです。

{
    "value": "6c83725d0b690a737d97805ce1d05d80"
}


8 既存のVMの一覧を取得

[VM]から"List"を選択し、[Send]をクリックします。
既存で存在する、VMの一覧が表示されるはずです。

9 VMの作成

[VM]から"Create with defaults"を選択し、[Send]をクリックします。
下記のエラーが発生し、VMは作成されません。

"default_message": "Resource pool with identifier 'resgroup-9' does not exist.",
"id": "com.vmware.api.vcenter.vm.resourcepool_not_found"

テンプレートに記載されている"resgroup-9"は実環境にないとエラーが表示されているようです。[BODY]タブの下記の項目を実環境に合わせて設定することで、エラーが発生しなくなります。

"datastore": "datastore-12",
"folder": "group-v7",
"resource_pool": "resgroup-9"

datastoreは[Collection]から[Datastores]にある[List]を実行することで取得可能です。
folderは[Collection]から[Folders]にある[List]を実行することで取得可能です。
resource_poolは[Collection]から[Resource Pool]にある[List]を実行することで取得可能です。

試験環境ではdatastore-25、group-v49、resgroup-10でしたので、この値を使うことにします。
[VM]の"Create with defaults"に戻り、Bodyの部分の下記の通り書き換えます。
{
    "spec": {
        "guest_OS": "RHEL_7_64",
        "placement" : {
            "datastore": "datastore-25",
            "folder": "group-v49",
            "resource_pool": "resgroup-10"
        }
    }
}

書き換えが完了したら、[Send]をクリックします。
下記のように、作成されたVMの番号が返ってきます。
{
    "value": "vm-73"
}


10.Pythonからの呼び出し

さて、Postmanで実行できることがわかったので、Pythonから適当に呼び出してみます。
nm0からnm9と名前の付いた10個の仮想マシンを作成します。
取り敢えずRESTの試験のため適当に作りましたので、実環境に適用する際はパスワードを暗号化して別に持つなど、コードを適切に書き換えてください。

import requests


def connect(vc, user, passwd):
    """
    vCenterに接続してSessionオブジェクトを返します。
    :param vc:      vCenterのFQDNかIPアドレス
    :param user:    ユーザ
    :param passwd:  パスワード
    :return:        Sessionオブジェクト
    """
    url = "https://{0}/rest/com/vmware/cis/session".format(vc)
    sess = requests.Session()
    sess.auth = (user, passwd)
    sess.verify = False
    res = sess.post(url)
    if res.status_code != 200:
        raise Exception(res.content)
    return sess


class VmCreator:
    """
    vm作ります!
    """
    def __init__(self, vc, session, datastore, folder, resource_pool):
        """
        :param vc:              vCenterのFQDNかIPアドレス
        :param session:         Sessionオブジェクト
        :param datastore:       Datastore
        :param folder:          Floder
        :param resource_pool:   Resource Pool
        """
        self._server = vc
        self._url = "https://{0}/rest/vcenter/vm".format(self._server)
        self._session = session
        placement = {
            "datastore": datastore,
            "resource_pool": resource_pool,
            "folder": folder
        }
        self._data = {"placement": placement}

    def set_name(self, value):
        self._data["name"] = value

    def set_guest_os(self, value):
        self._data["guest_OS"] = value

    def set_memory(self, size, hot_add=False):
        memory = {
            "size_MiB": size,
            "hot_add_enabled": hot_add
        }
        self._data["memory"] = memory

    def get_data(self):
        return self._data

    def set_cpu(self, socket, core, hotadd=False, hotremove=False):
        cpu = {
            "count": socket,
            "cores_per_socket": core,
            "hot_add_enabled": hotadd,
            "hot_remove_enabled": hotremove
        }
        self._data["cpu"] = cpu

    def add_disk(self, capacity):
        disk = {"new_vmdk": {"capacity": capacity}}
        if "disks" not in self._data:
            self._data["disks"] = []
        self._data["disks"].append(disk)

    def add_cdrom(self, path):
        cdrom = {
            "type": "IDE",
            "backing": {
                "iso_file": path,
                "type": "ISO_FILE"
            }
        }
        if "cdroms" not in self._data:
            self._data["cdroms"] = []
        self._data["cdroms"].append(cdrom)

    def create(self):
        param = {"spec": self._data}
        res = self._session.post(self._url, json=param)
        if res.status_code != 200:
            raise Exception(res.content)
        return res.content


vcs = "xxx.xxx.xxx.xxx"                         # vCenterServerのIPかFQDN
us = "xxxxxxxxx@vsphere.local"                  # user
ps = "XXXXXXXXXXXXXXXX"                         # password

s = connect(vcs, us, ps)
v = VmCreator(vcs, s, "datastore-XX", "group-vXX", "resgroup-XX")
v.set_guest_os("RHEL_7_64")
v.set_cpu(2, 2)                                 # Socket, Core
v.set_memory(4096, True)                        # 4096MByte
v.add_disk(10*1024*1024*1024)                   # 10GByte
v.add_disk(1024*1024*1024)                      # 1GByte
v.add_cdrom("[datastore1-2] image/CentOS-7-x86_64.iso")

# nm0からnm9までの仮想マシンを作成します。
for i in range(0, 10):
    v.set_name("nm{0}".format(i))               # vm name
    v.create()



無事10個の仮想マシンを作成できることが確認できました。
どんなパラメータ投げてるかは、postのparamをjson.dumpsしてみればわかると思います。

vSphereは元々APIが豊富でしたが、利用にはPerlを入れたりライブラリを入れたりでいろいろと準備が必要でした。RESTで書けるようになることでAPIの利用の敷居が低くなり、色々はかどりそうな気がします。

0 件のコメント:

コメントを投稿