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/ipsget_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.pyset_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