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 |
リモートストレージシステムのシリアル番号です。 |
サンプルコードの内容
サンプルコードの内容について説明します。
-
必要なライブラリのインポートおよびパラメータの設定
リモートストレージシステムの情報登録の処理を開始する前に、必要なライブラリやクラスをインポートします。サンプルコードでは、共通ライブラリのほか、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") ########################################################### -
ヘッダの定義
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 ########################################################### -
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] -
REST APIのバージョンの確認
ローカルストレージシステム側とリモートストレージシステム側のそれぞれのREST APIサーバで、REST APIのバージョン情報を取得し、サポートしているバージョンであることを確認します。- ヒント
-
次の場合は、ストレージシステムのマイクロコードのバージョンが適切であるかどうかも確認してください。
- REST APIサーバとストレージシステム間でSSL通信を利用する場合
- ストレージシステムがVSP 5000 シリーズ、VSP E シリーズ、VSP G150、G350、G370、G700、G900、VSP 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) -
セッションの作成
ローカルストレージシステム側とリモートストレージシステム側のそれぞれの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は、一連の操作が終了したあと、セッションを破棄するときに使用します。
-
リモートストレージシステムの情報登録
ローカルストレージシステム側の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を実行結果として返し ます。
-
登録したリモートストレージシステムの情報取得
リモートストレージシステムの情報が正しく登録されていることを確認するため、ローカルストレージシステム側の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サーバのポート番号、モデル名、シリアル番号を取得し、出力しています。
-
エラーメッセージの出力
サンプルコードでは、通信エラー、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") -
セッションの破棄
一連の操作が完了したら、ローカルストレージシステム側とリモートストレージシステム側の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()