背景
弊社から提供したNetAppの使用状況を調査したいという要望がお客様よりありました。一般的には、PowerShellとかで、最終アクセス日や変更日などを取得するスクリプトで取得するのですが、NetAppは、別マシンからネットワーク越しに実施するので、遅くなりそうということで、初めてNetAppのAPIを試すことにしました。
NetApp(ONTAP)のAPI仕様
NetApp上のOSであるONTAPは9.6以降にAPIが使えるようになったようです。お客様に提供しているOSを確認したところ、利用できそうということで、早速ONTAP REST APIのマニュアルから読んでみました。
以下のサイトにマニュアルが有るようです。
https://<cluster-ip-address>/docs/api
注意点
実装にあたり注意点は、3つありました。
ユーザIDとパスワードの渡し方にクセがありました。curlコマンドで直接パスワードを入れて実行する場合、パスワードに記号が入っているとcurlの基本認証でうまくコマンドが認識しませんでした。なので、$passのようなシェル変数に入れました。最終的にはPythonで実装するのであまり問題ではないですが、テストが想定通りデータが取れないので、少し苦戦しました。
curl -siku ${user}:${pass} -X GET "https://xxx.xxx.xxx.xxx/api/storage/volumes/${uuid}/files/%2F?fields=accessed_time&order_by=accessed_time+asc"
VPN経由でアクセスすると、何百回に1回ぐらいの頻度で応答がないときがありました。初めはAPIのアクセス制限があるのかと思ったのですが、調べたところ見当たらなかったので、requests.Session()を使って、リトライをすることにしました。
session = requests.Session()
retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
session.mount('https://', HTTPAdapter(max_retries=retries))
フォルダの区切り文字「/」や「\(¥)」などをエンコードした文字列にする必要がありました。実際のAPIの中では、フォルダやファイルのオブジェクトが持っている「href」キーを引数にすることで、その最終アクセス日を取得できましたが、実際対象のデータがどのフォルダにあったのかを確認する際に、わざわざエンコードをしなくてはいけないのが面倒でした。
Postmanでのテスト
APIの仕様をある程度把握できたので、Postmanを使ってデータの取り方や戻ってきたデータなどを確認しました。
Pythonで実装
フォルダ内のフォルダを取得
対象フォルダ内のフォルダ一覧を取得する部分は、トップディレクトリは「/」なので、"%2F"で、それ以降は個別に取得した「href」を調査することにしました。後は、「.」や「..」を除外しています。
def get_folder_name(directory):
global session
if directory == '%2F':
api_url = '/api/storage/volumes/' + uuid + '/files/' + directory
else:
api_url = directory
try:
res = session.get(url + api_url, auth=HTTPBasicAuth(user, password), verify=False, timeout=3.0)
except requests.exceptions.Timeout:
print(f'Error:{directory}の応答がありません')
folder_json = [x for x in res.json()['records'] if
x['type'] == 'directory' and (x['name'] != '.' and x['name'] != '..')]
return folder_json
フォルダ内のファイルの最終アクセス日を取得
ここはシンプルにフォルダ内の各ファイルの最終アクセス日を「accessed_time」を取得してます。見やすいように古い順に表示しています。
def get_accessed_time(directory):
global session
api_url = directory + '?fields=accessed_time&order_by=accessed_time+asc'
try:
res = session.get(url + api_url, auth=HTTPBasicAuth(user, password), verify=False, timeout=3.0)
except requests.exceptions.Timeout:
print(f'{directory}の応答がありません')
return res.json()['records']
コメント