Hitachi

Hitachi Command Suite Configuration Manager REST API リファレンスガイド


21.5 リモートストレージシステムの情報登録のサンプルコード

リモートストレージシステムの情報登録のサンプルコードについて説明します。

リモートストレージシステムの情報登録のサンプルコードの流れ

リモートストレージシステムの情報登録のサンプルコードの流れと、対応するコードの構成要素を次に示します。
ステップ

サンプルコードの流れ

コードの構成要素

1

必要なライブラリのインポートおよびパラメータの設定

2

ヘッダの定義

リクエストヘッダの指定(既定のHTTPヘッダの場合)

3

HTTPリクエストの発行と非同期処理の状態確認のための関数の定義

GET操作によるジョブの状態取得

JSON形式によるリクエストボディの生成

ユーザ認証情報の設定(セッションベースの認証の場合)

ジョブの実行結果の取得

操作結果が反映されたリソースのURL取得

エラーコードの取得

4

REST APIのバージョンの確認

GET操作によるREST APIバージョン情報の取得

5

セッションの生成

リソースのURL取得(オブジェクトIDを指定しない場合)

ユーザ認証情報の設定(ユーザIDとパスワードによる認証の場合)

POST操作によるオブジェクトの新規作成

6

ストレージシステムの情報登録

リソースのURL取得(オブジェクトIDを指定しない場合)

JSON形式によるリクエストボディの生成

複数装置でのセッション生成を必要とする操作(リモートコピー操作)

POST操作によるオブジェクトの新規作成

7

ストレージシステムの情報取得

リソースのURL取得(操作結果から取得したオブジェクトIDを指定する場合)

ユーザ認証情報の設定(セッションベースの認証の場合)

GET操作によるオブジェクトの取得(特定のオブジェクトを取得する場合)

取得した情報の出力

8

エラーメッセージの出力

エラーメッセージの出力

9

セッションの破棄

リソースのURL取得(操作結果から取得したオブジェクトIDを指定する場合)

DELETE操作によるオブジェクトの削除

想定するシステム構成

このサンプルコードでは、次の概念図のようなシステム構成を想定しています。

[図データ]

サンプルコードのパラメータに設定している値を次に示します。必要に応じて、システムの環境や要件に合わせた設定に変更してください。

パラメータ

設定値

説明

LOCAL_USER _CREDENTIAL

("local_user", "local_pass")

ローカルストレージシステムでの認証に使用する認証情報です。サンプルコードの例は、ユーザIDがlocal_user、パスワードがlocal_passの場合の設定例です。ユーザには、ストレージ管理者(初期設定)ロールが必要です。

REMOTE_USER _CREDENTIAL

("remote_user", "remote_pass")

リモートストレージシステムでの認証に使用する認証情報です。サンプルコードの例は、ユーザIDがremote_user、パスワードがremote_passの場合の設定例です。ユーザには、ストレージ管理者(初期設定)ロールが必要です。

FIRST_WAIT_TIME

1

非同期処理の実行結果を取得する1回目の間隔(秒)です。通常は変更する必要はありません。

MAX_RETRY_COUNT

10

非同期処理の実行結果を取得する最大リトライ回数です。通常は変更する必要はありません。

また、ローカルストレージシステムおよびリモートストレージシステムの情報を、サンプルコード間での共通変数として使うために、remote_copy_param.pyファイルに定義したパラメータと値を次に示します。こちらも、必要に応じて、システムの環境や要件に合わせた設定に変更してください。

パラメータ

設定値

説明

LOCAL_REST_SERVER_IP_ADDR

192.0.2.100

ローカルストレージシステム側のREST APIサーバの IPアドレスです。

LOCAL_PORT

23451

ローカルストレージシステム側のREST APIサーバのSSL通信用ポートです。

LOCAL_STORAGE_MODEL

VSP G800

ローカルストレージシステムのモデル名です。

LOCAL_SERIAL_NUMBER

410000

ローカルストレージシステムのシリアル番号です。

REMOTE_REST_SERVER_IP_ADDR

192.0.2.200

リモートストレージシステム側のREST APIサーバの IPアドレスです。

REMOTE_PORT

23451

リモートストレージシステム側のREST APIサーバのSSL通信用ポートです。

REMOTE_STORAGE_MODEL

VSP G200

リモートストレージシステムのモデル名です。

REMOTE_SERIAL_NUMBER

420000

リモートストレージシステムのシリアル番号です。

サンプルコードの内容

サンプルコードの内容について説明します。

  1. 必要なライブラリのインポートおよびパラメータの設定

    リモートストレージシステムの情報登録の処理を開始する前に、必要なライブラリやクラスをインポートします。サンプルコードでは、共通ライブラリのほか、URLを生成する関数を定義したBlockStorageAPIクラスをインポートしています。
    # coding:utf-8
    
    """
    register_remote_storage
    
    This program requires API version 1.3.x or newer.
    """
    
    import traceback
    import requests
    import json
    import sys
    import http.client
    import time
    import remote_copy_param
    
    from block_storage_api import BlockStorageAPI
    
    サンプルコード内で使用するパラメータを設定します。
    # #################Initialize parameters################# #
    # Change the following parameters to fit your environment
    
    # This parameter defines the first interval to access
    # an asynchronous job. (Unit: Second)
    FIRST_WAIT_TIME = 1
    
    # This parameter defines the maximum retry time
    # to confirm job status.
    MAX_RETRY_COUNT = 10
    
    # An user id and password of the local storage
    LOCAL_USER_CREDENTIAL = ("local_user", "local_pass")
    
    # An user id and password of the remote storage
    REMOTE_USER_CREDENTIAL = ("remote_user", "remote_pass")
    
    ###########################################################
    
  2. ヘッダの定義

    HTTPリクエストヘッダを定義します。REST APIはJSON形式のデータだけをサポートしているため、データをJSON形式で扱うようヘッダ情報を定義しておきます。
    # ###You don't have to change the following parameters### #
    local_storage_api = BlockStorageAPI(
        remote_copy_param.LOCAL_REST_SERVER_IP_ADDR,
        remote_copy_param.LOCAL_PORT,
        remote_copy_param.LOCAL_STORAGE_MODEL,
        remote_copy_param.LOCAL_SERIAL_NUMBER)
    
    remote_storage_api = BlockStorageAPI(
        remote_copy_param.REMOTE_REST_SERVER_IP_ADDR,
        remote_copy_param.REMOTE_PORT,
        remote_copy_param.REMOTE_STORAGE_MODEL,
        remote_copy_param.REMOTE_SERIAL_NUMBER)
    
    local_headers = {"content-type": "application/json",
                     "accept": "application/json",
                     "Response-Job-Status": "Completed"}
    
    remote_headers = {"content-type": "application/json",
                      "accept": "application/json",
                      "Response-Job-Status": "Completed"}
    
    REQUIRED_MAJOR_VERSION = 1
    REQUIRED_MINOR_VERSION = 3
    
    local_session_id = 0
    remote_session_id = 0
    
    ###########################################################
    
  3. HTTPリクエストの発行と非同期処理の状態確認のための関数の定義(invoke_async_command関数)

    HTTPリクエストの発行と非同期処理の状態を確認する関数を定義します。この関数は、メインのリモートストレージシステムの情報登録から呼び出して使用します。この関数の詳細については、サンプルコードで使用している関数の説明を参照してください。

    ヒント

    サンプルコードでは、REST APIクライアントとストレージシステム間のSSL通信で使用するサーバ証明書が自己署名証明書の場合に発生するエラーを回避するため、リクエスト発行時にverify=Falseを指定することでサーバ証明書の検証処理をスキップしています。

    """
    Check whether the asynchronous command was finished.
    
    @param storage_api storage_api
    @param job_id the job ID to identify
    the asynchronous command
    @param headers the array of the http headers
    @return r the response data
    """
    
    
    def check_update(storage_api, job_id, headers):
        url = storage_api.job(str(job_id))
        r = requests.get(url, headers=headers, verify=False)
        return r
    
    """
    Execute the HTTP request (POST or PUT)
    
    @param storage_api storage_api
    @param method_type HTTP request method (POST or PUT)
    @param headers the array of the http headers
    @param url URL to execute HTTP method
    @param body The information of a resource
    @return job_result.json()["affectedResources"][0]
             URL of an affected resource
    """
    
    
    def invoke_async_command(storage_api, method_type, headers,
                             url, body):
        if method_type == "put":
            r = requests.put(url, headers=headers,
                             data=json.dumps(body), verify=False)
        elif method_type == "post":
            r = requests.post(
                url,
                headers=headers,
                data=json.dumps(body),
                verify=False)
        if r.status_code != http.client.ACCEPTED:
            raise requests.HTTPError(r)
        print("Request was accepted. JOB URL : " +
              r.json()["self"])
        status = "Initializing"
        job_result = None
        retry_count = 1
        wait_time = FIRST_WAIT_TIME
        while status != "Completed":
            if retry_count > MAX_RETRY_COUNT:
                raise Exception("Timeout Error! "
                                "Operation was not completed.")
            time.sleep(wait_time)
            job_result = check_update(storage_api,
                                      r.json()["jobId"], headers)
            status = job_result.json()["status"]
            double_time = wait_time * 2
            if double_time < 120:
                wait_time = double_time
            else:
                wait_time = 120
            retry_count += 1
        if job_result.json()["state"] == "Failed":
            error_obj = job_result.json()["error"]
            if "errorCode" in error_obj:
                if "SSB1" in error_obj["errorCode"]:
                    print("Error! SSB code : ",
                          error_obj["errorCode"]["SSB1"],
                          ", ", error_obj["errorCode"]["SSB2"])
                elif "errorCode" in error_obj["errorCode"]:
                    print("Error! error code : ",
                          error_obj["errorCode"]["errorCode"])
            raise Exception("Job Error!", job_result.text)
        print("Async job was succeeded. affected resource : " +
              job_result.json()["affectedResources"][0])
        return job_result.json()["affectedResources"][0]
    
  4. REST APIのバージョンの確認

    ローカルストレージシステム側とリモートストレージシステム側のそれぞれのREST APIサーバで、REST APIのバージョン情報を取得し、サポートしているバージョンであることを確認します。
    ヒント

    次の場合は、ストレージシステムのマイクロコードのバージョンが適切であるかどうかも確認してください。

    • REST APIサーバとストレージシステム間でSSL通信を利用する場合
    • ストレージシステムがVSP 5000 シリーズVSP E シリーズVSP G150、G350、G370、G700、G900VSP F350、F370、F700、F900の場合

    REST APIのバージョンとストレージシステムのマイクロコードのバージョンの対応については、Configuration Managerバージョン対応表を参照してください。

    """
    Check whether this API version allows the REST
     Server to execute this program
    
    @param api version api_version of this REST Server
    @param required_major_version the lowest number of
    the major version that this program requires
    @param required_minor_version the lowest number of
    the minor version that this program requires
    
    """
    
    
    def check_api_version(api_version, required_major_version,
                          required_minor_version):
        version = api_version.split(".")
        major_version = int(version[0])
        minor_version = int(version[1])
        if not ((major_version == required_major_version and
                 minor_version >= required_minor_version) or
                major_version >= required_major_version + 1):
            sys.exit("This program requires API Version " +
                     str(required_major_version) + "." +
                     str(required_minor_version) +
                     "." + "x or newer.\n")
    
    try:
        # step1 Check the API version of the local REST API #
        print("Check the API version of the local REST API")
        url = local_storage_api.api_version()
        r = requests.get(url, headers=local_headers,
                         verify=False)
        if r.status_code != http.client.OK:
            raise requests.HTTPError(r)
        check_api_version(r.json()["apiVersion"],
                          REQUIRED_MAJOR_VERSION,
                          REQUIRED_MINOR_VERSION)
    
        # step1 Check the API version of the remote REST API #
        print("Check the API version of the remote REST API")
        url = remote_storage_api.api_version()
        r = requests.get(url, headers=remote_headers,
                         verify=False)
        if r.status_code != http.client.OK:
            raise requests.HTTPError(r)
        check_api_version(r.json()["apiVersion"],
                          REQUIRED_MAJOR_VERSION,
                          REQUIRED_MINOR_VERSION)
    
  5. セッションの作成

    ローカルストレージシステム側とリモートストレージシステム側のそれぞれのREST APIサーバで、セッションを生成します。
        # step2 Generate a local session #
        print("Generate a local session")
        url = local_storage_api.generate_session()
        r = requests.post(
            url,
            headers=local_headers,
            auth=LOCAL_USER_CREDENTIAL,
            verify=False)
        if r.status_code != http.client.OK:
            raise requests.HTTPError(r)
        local_token = r.json()["token"]
        local_auth = "Session " + local_token
        local_session_id = r.json()["sessionId"]
    
        # step2 Generate a remote session #
        print("Generate a remote session")
        url = remote_storage_api.generate_session()
        r = requests.post(url, headers=remote_headers,
                          auth=REMOTE_USER_CREDENTIAL,
                          verify=False)
        if r.status_code != http.client.OK:
            raise requests.HTTPError(r)
        remote_token = r.json()["token"]
        remote_auth = "Session " + remote_token
        remote_session_id = r.json()["sessionId"]
        remote_headers["Authorization"] = remote_auth
    

    セッションを生成すると、セッションIDとトークンが返却されます。トークンは、これ以降の操作で必要な認証情報として、API実行時にAuthenticationヘッダに指定します。セッションIDは、一連の操作が終了したあと、セッションを破棄するときに使用します。

  6. リモートストレージシステムの情報登録

    ローカルストレージシステム側のREST APIサーバに、リモートストレージシステムの情報を登録します。 リクエストボディには、リモートストレージシステムの情報を指定します。
        # step3 Register a remote storage device #
        print("Register a remote storage device")
        url = local_storage_api.remote_storage()
        body = {
            "storageDeviceId": remote_storage_api.
            get_storage_id(),
            "restServerIp": remote_copy_param.REMOTE_REST_SERVER_IP_ADDR,
            "restServerPort": remote_copy_param.REMOTE_PORT
        }
        local_headers["Authorization"] = local_auth
        local_headers["Remote-Authorization"] = remote_auth
        affected_resource_path = invoke_async_command(
            local_storage_api, "post",
            local_headers, url, body)
    

    invoke_async_command 関数は、リモートストレージシステムの情報を登録するリクエストを発行し、非同期に実行されるジョブの実行状態を確認して、登録したストレージシステムのURLを実行結果として返し ます。

  7. 登録したリモートストレージシステムの情報取得

    リモートストレージシステムの情報が正しく登録されていることを確認するため、ローカルストレージシステム側のREST APIサーバで、登録されているストレージシステムの情報を取得します。
        # step4 Print the remote storage device #
        print("Print the remote storage device")
        url = local_storage_api.affected_resource(
            affected_resource_path)
        r = requests.get(url, headers=local_headers,
                         verify=False)
        if r.status_code != http.client.OK:
            raise requests.HTTPError(r)
        print("STORAGE DEVICE ID : " +
              str(r.json()["storageDeviceId"]))
        print("DKC TYPE : " + str(r.json()["dkcType"]))
        print("REST SERVER IP : " + str(r.json()["restServerIp"]))
        print("REST SERVER PORT : " + str(r.json()["restServerPort"]))
        print("MODEL : " + str(r.json()["model"]))
        print("SERIAL NUMBER : " +
              str(r.json()["serialNumber"]))
    

    サンプルコードでは、ストレージデバイスID、ストレージシステムの種別、リモートストレージシステム側のREST APIサーバのIPアドレス、リモートストレージシステム側のREST APIサーバのポート番号、モデル名、シリアル番号を取得し、出力しています。

  8. エラーメッセージの出力

    サンプルコードでは、通信エラー、HTTP リクエストエラー、ジョブ実行時エラーの処理を記載しています。通信エラーの場合は、エラーメッセージを出力します。HTTP リクエストエラーの場合は、エラーコードとメッセージ、レスポンスボディを出力します。ジョブ実行時エラーの場合は、ジョブの実行結果に含まれる内容をすべて出力します。
    except requests.ConnectionError:
        sys.stderr.write("Connection Error!\n")
        sys.stderr.write(traceback.format_exc())
    except requests.HTTPError as he:
        sys.stderr.write("HTTP Error! status code : ")
        sys.stderr.write(str(he.args[0].status_code) + "\n")
        sys.stderr.write(he.args[0].text + "\n")
    except Exception as e:
        sys.stderr.write(traceback.format_exc())
        for msg in e.args:
            sys.stderr.write(str(msg) + "\n")
    
  9. セッションの破棄

    一連の操作が完了したら、ローカルストレージシステム側とリモートストレージシステム側のREST APIサーバで、セッションを破棄します。セッションの作成時に取得したセッションIDを指定します。サンプルコードでは、APIの実行中にエラーが発生した場合にも必ずセッションが破棄されるよう、finally句で記述しています。セッションを破棄したら、処理を終了します。
    finally:
        # step5 Discard the local session #
        print("Discard the local session")
        url = local_storage_api.discard_session(
            local_session_id)
        r = requests.delete(url, headers=local_headers,
                            verify=False)
        if r.status_code != http.client.OK:
            raise requests.HTTPError(r)
    
        # step5 Discard the remote session #
        print("Discard the remote session")
        url = remote_storage_api.discard_session(
            remote_session_id)
        r = requests.delete(url, headers=remote_headers,
                            verify=False)
        if r.status_code != http.client.OK:
            raise requests.HTTPError(r)
    
        print("Operation was completed.")
        sys.exit()