Tintri VMstoreにおけるデータのIP設定
Tintriの技術開発の伝道師であり、技術者のRick Ehrhartのブログです。自身のコラムでITに関する問題を取り上げ、Tintriのストレージを使った簡単な解決方法を伝授しています。
Rick
こんにちは
いつもブログを楽しく拝見し、Tintriの自動化に役立てています。現在、Tintriのプロビジョニングの自動化に取り組んでいますが、データのIPをrest APIで設定することに手間取っています。IPS(侵入防止システム)をリストアップするgetメソッド([v310/appliance/%7buuid7d/ips/index.html]/v310/appliance/{uuid}/ips)は利用できるものの、ドキュメンテーションにIPを設定するpostメソッドは見つかりませんでした。 データのIPはTintri Automation PowerShell Toolkitで設定できますが、個人的にはREST APIの方が好きです。REST APIによるデータのIP設定を近日中に可能にする予定はありますか。
Gaurav
こんにちは
データのIP設定はDNSの設定に似ています。 PUT /v310/appliance/default
のAPIを使うのです。 例としてset_data_ip.pyを紹介します。これは、現在のIPアドレスを表示し、データのIPアドレスを追加または削除するものです。
[rle@rle-vm tintri-api-examples]$ ./set_data_ip.py -h
usage: set_data_ip.py [-h] [--add ADD] [--delete DELETE]
server_name user_name password
Optionally adds or deletes a data IP on a VMstore
positional arguments:
server_name VMstore server name
user_name VMstore user name
password User name password
optional arguments:
-h, --help show this help message and exit
--add ADD, -a ADD Add the specifed IP to the data IP configuration.
--delete DELETE, -d DELETE
Delete the specifed IP from the data IP configuration.
set_dns_primary.pyでDNSアドレスを取得する代わりに、このコードは GET /v310/appliance/default/ips
を get_ip_configs
ファンクションとともに用いることで、現在のVMstoreのIPアドレスを取得します。
APPLIANCE_URL = "/v310/appliance/default"
# Return IP addresses.
def get_ip_configs(server_name, session_id):
url = APPLIANCE_URL + "/ips"
try:
# Make the get call
r = tintri.api_get(server_name, url, session_id)
print_debug("The JSON response of the get invoke to the server " +
server_name + " is: " + r.text)
except tintri.TintriRequestsException as tre:
message = HTTP error for the get IP addresses invoke to the server."
raise tintri.TintriApiException(message, r.status_code, url, str(Request), r.text)
except tintri.TintriApiException as tae:
message = "The HTTP response for the get IP addresses invoke to the server is not 200."
raise tintri.TintriApiException(message, r.status_code, url, str(Request), r.text)
ip_configs = r.json()
return ip_configs
ここで忘れてはならないのは、アプライアンスAPIはUUIDを必要とし、VMstoreでAPIを呼び出す際にはAPI “default”
が使われます。 GET /v310/appliance/default
を使うこともできますが、検索する情報量が少ない分、 GET /v310/appliance/default/ips
の方が速いのです。 set_dns_primary.pyとset_data_ip.pyの大きな違いは、set_dns_primary.pyは複数のVMstoreを設定するのに対し、set_data_ip.pyは一つのVMstoreしか設定しないことです。これによりコードは単純化されますが、サーバーの仮想ストレージ化は依然として可能です。
try:
r = tintri.api_version(server_name)
json_info = r.json()
if json_info['productName'] != "Tintri VMstore":
message = "Server needs to be a VMstore"
raise tintri.TintriRequestsException(message)
上記の例には異なるアップデート コンテンツが含まれている可能性があるため、 PUT v310/appliance/default
のAPIを呼び出すコードとコンテンツを作成するコードを区別しました。APIの呼び出しは update_data_ip( )
で、アップデート コンテンツの作成は add_data_ip( )
もしくは delete_data_ip( )
で行われます。これは、使用するコマンドラインオプションに左右されます。 下記の update_data_ip( )
ファンクションでは、 new_ip_configs
を用い、 configIps
のDTOをインプットとして表します。 Request
のDTOには、更新される値とプロパティを持つオブジェクトが含まれています。この場合、データ用IPアドレスの値を持つオブジェクトは new_appliance
で、変更されるプロパティが configIps
となります。これもまた、set_dns_primary.pyにおける process_vmstore( )
に似ています。
# Set the data IP with new IP configuration.
def update_data_ip(server_name, session_id, new_ip_configs):
# Create the Appliance object with the new configIps DTO.
new_appliance = \
{'typeId': 'com.tintri.api.rest.v310.dto.domain.Appliance',
'configIps': new_ip_configs
}
# Create the Request object with the Appliance DTO.
Request = \
{'typeId': 'com.tintri.api.rest.v310.dto.Request',
'objectsWithNewValues': newAppliance,
'propertiesToBeUpdated': ['configIps']
}
# Update the VMstore wit the new data IP configuration.
url = APPLIANCE_URL
r = tintri.api_put(server_name, url, Request, session_id)
print_debug("The JSON response of the get invoke to the server " +
server_name + " is: " + r.text)
# if HTTP Response is not 204 then raise exception.
if r.status_code != 204:
message = "The HTTP response for put call to the server is not 204."
raise tintri.TintriApiException(message, r.status_code, url, str(Request), r.text)
最初にadd_data_ip( )
を見てみましょう。PUT v310/appliance/default
はデータのIPアドレスを更新するため、現在の設定済みIPアドレスリストから、データのIPアドレスだけ見つければよいのです。各データのIPアドレスについては、コードが新しいリストに追加します。また、データ用IPアドレスの設定は、後で新しいデータIPアドレスのテンプレートとして使うために保存されます。ループ後に、保存されたデータIPアドレスの設定を変更することにより新しいデータIPアドレスが作成されます。ここで注意することはVLAN IDは untagged
と表示されることです。しかし、ネットワークでVLANを使用している場合、この値は untagged
ではなくVLAN IDとなります。新しいデータIPアドレスの設定は、設定済みIPアドレスのリストに追加され、リストは送信側に戻されます。
# Add a data IP to the list of current IPs and return new list.
def add_data_ip(ip_configs, new_data_ip):
new_ip_configs = []
# Find a data IP config to copy and copy only the data IP configs.
for ip_config in ip_configs:
if (ip_config['ip'] == new_data_ip):
message = new_data_ip + " already configured."
raise tintri.TintriRequestsException(message)
if (ip_config['serviceType'] == "data"):
ip_config_save = ip_config
new_ip_configs.append(ip_config)
if (not ip_config_save):
message = "Data IP conifg does not exist."
raise tintri.TintriRequestsException(message)
data_ip_config = ip_config_save.copy()
# Modify the save copy for our purposes.
data_ip_config['ip'] = new_data_ip
data_ip_config['vlanId'] = "untagged" # For example only.
new_ip_configs.append(data_ip_config)
return new_ip_configs
IPアドレスを削除するには新しいデータIPアドレスのリストが再び必要になります。ご覧のように、これはIPアドレスの追加よりも簡単です。コードは設定リストをざっと調べ、特定のIPアドレスに適合するIPアドレスの設定を、新しいデータIPアドレスの設定リストに追加することはありません。
def del_data_ip(ip_configs, data_ip_to_del):
new_ip_configs = []
# Append IP config if the data IP doesn't match.
for ip_config in ip_configs:
if (ip_config['serviceType'] == "data"):
if (ip_config['ip'] != data_ip_to_del):
new_ip_configs.append(ip_config)
return new_ip_configs
それでは最後のコードを見てみましょう。現在のIPアドレス設定は常に表示されます。追加オプションまたは削除オプションが指定されると、指定された作業が実行され、新しいIPアドレスの設定が表示されます。
# Execute
try:
ip_configs = get_ip_configs(server_name, session_id)
print_ip_configs(ip_configs, "Current")
if add_ip or delete_ip:
if add_ip:
new_ip_configs = add_data_ip(ip_configs, new_data_ip)
if delete_ip:
new_ip_configs = del_data_ip(ip_configs, new_data_ip)
update_data_ip(server_name, session_id, new_ip_configs)
# Display the changes
ip_configs = get_ip_configs(server_name, session_id)
print_ip_configs(ip_configs, "New")
except tintri.TintriRequestsException as tre:
print_error(server_name + ": " + tre.__str__())
except tintri.TintriApiException as tae:
print_error(server_name + ": " + tae.__str__())
なお、Tintri GitHubサイトのほうがコーディング経験に関する事例が多く記載されていますので、チェックされてはいかがでしょうか。 他にもご質問があれば、お気軽にどうぞ。
Rick