{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# S3準拠オブジェクトストレージを大容量データの保管場所として使う\n", "\n", "このNotebookは[AWS S3](https://aws.amazon.com/jp/s3/)に準拠したオブジェクトストレージを大容量データの保管場所として利用する際のサポートを提供します。\n", "\n", "## データガバナンス機能における大容量データの管理について\n", "\n", "データガバナンス機能では、大容量データの管理にあたって、データファイルのメタデータ(ファイル名、作成日時、実データの所在等の情報)と実データとを分けて管理することができる技術「git-annex」を採用しています。これにより、目下必要となる実データのみをこの実験環境にダウンロードできるため、データ利用の利便性が向上するメリットがあります。このNotebookでは、この管理手法を用いた実データの操作をサポートします。\n", "\n", "## このNotebookでできること(ユースケース例を基に)\n", "\n", "### 例① データをgit-annex管理下へ移管する\n", "\n", "![usecase_annex_s3_1](https://raw.githubusercontent.com/NII-DG/workflow-template/main/PACKAGE/base/EX-WORKFLOW/images/usecase_annex_s3_1.png)\n", "\n", "### 例② git-annex管理下のデータを利用する\n", "\n", "![usecase_annex_s3_2](https://raw.githubusercontent.com/NII-DG/workflow-template/main/PACKAGE/base/EX-WORKFLOW/images/usecase_annex_s3_2.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 0.オブジェクトストレージとの接続設定をする\n", "\n", "データ保管の場所として、オブジェクトストレージをシステムが認識するための設定を行います。\n", "\n", "※ここでは、適切なキーとシークレットアクセスキーとのIDが必要です。詳しくは、各オブジェクトストレージのドキュメントをご覧いただくか、各管理者にお問い合わせください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "from IPython.display import clear_output\n", "\n", "# 将来的にはGRDM等を利用したキー情報管理を検討する\n", "os.environ['AWS_ACCESS_KEY_ID'] = input('アクセスキーID: ')\n", "os.environ['AWS_SECRET_ACCESS_KEY'] = input('シークレットアクセスキー: ')\n", "\n", "clear_output()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ipywidgets as widgets\n", "from IPython.display import display\n", "\n", "def on_click_callback(clicked_button: widgets.Button) -> str:\n", " with output:\n", " output.clear_output()\n", " # セレクタで選択されているアイテムを使う\n", " print(f'{select.value}が選択されました。')\n", " print('次のセルでは、このオブジェクトストレージへの接続処理を進めます。')\n", " print('選択したストレージでよろしければ、次のセルの実行へお進みください。')\n", " print('もし選び直す場合は、もう一度上のボックスから選択した後、「決定」ボタンを押してください。')\n", " \n", "print('どのオブジェクトストレージ(S3)を使いますか?')\n", "print('\\t※AWS: Amazon Web Service上で稼働するストレージ\\n\\t mdx: mdx環境上で稼働するストレージ')\n", "\n", "list_s3 = ['AWS', 'mdx']\n", "\n", "# select.valueの値を次のセルで処理の場合分けに利用する\n", "select = widgets.Select(options=list_s3)\n", "button = widgets.Button(description='決 定')\n", "button.on_click(on_click_callback)\n", "\n", "output = widgets.Output(layour={'border': '1px solid black'})\n", "\n", "display(select, button, output)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('データをアップロード/ダウンロードしたいオブジェクトストレージのバケット名を入力してください。')\n", "print('入力された名前のバケットがなければ作成され、あればその既存のバケットが利用されます。')\n", "bucket_name = input('バケット名:')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Note: 前までのセルから、select.valueとbucket_nameとを利用している\n", "\n", "import time\n", "\n", "# 次のセルでも利用する変数のため、関数の外で宣言している\n", "special_remote_name = 'remote_' + select.value + '_' + bucket_name\n", "\n", "def connect_s3_storage():\n", " print('接続設定中です...')\n", " try:\n", " msg = ''\n", " if select.value == 'AWS':\n", " # for Amazon Web Service(AWS) S3\n", " msg = !git-annex initremote $special_remote_name type=S3 bucket=$bucket_name encryption=none autoenable=true\n", " elif select.value == 'mdx':\n", " # for mdx(s3ds.mdx.jp) S3\n", " msg = !git-annex initremote $special_remote_name type=S3 port=443 host=s3ds.mdx.jp bucket=$bucket_name encryption=none signature=v2 requeststyle=path autoenable=true\n", " else:\n", " raise ValueError('select.value is wrong: ' + select.value) \n", " \n", " if msg[0] in 'There is already a special remote':\n", " !git-annex enableremote $special_remote_name\n", " print(select.value + 'への接続設定が完了しました。')\n", " except:\n", " print('処理を完了できませんでした。\\n利用するオブジェクトストレージが選択されていない可能性があります。')\n", " print('前のセルを実行いただき、利用したいオブジェクトストレージを選んでください。')\n", " print('もし選択してもこのメッセージが表示されている場合、恐れ入りますがデータガバナンス機能ヘルプセンター(仮)へお問い合わせください。')\n", " return\n", "\n", "if __name__ == '__main__':\n", " connect_s3_storage()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1-A. 実データをオブジェクトストレージへ保存する\n", "\n", "この手順では、任意のデータを「git-annex」による管理下に置き、「0.オブジェクトストレージとの接続設定をする」で設定したオブジェクトストレージへ、実データをアップロードする処理のサポートを提供します。\n", "\n", "以下のセルを順番に実行し、表示にしたがって操作することでデータをアップロードできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフォルダ内のフォルダ構造を取得し、どれをannex管理するか決める\n", "import os\n", "import ipywidgets as widgets\n", "from ipywidgets import Layout\n", "from IPython.display import display\n", "\n", "from scripts import utils\n", "\n", "####################################################################################################\n", "########################################## callback functions ######################################\n", "####################################################################################################\n", "def on_click_callback(clicked_button: widgets.Button) -> None:\n", " with output:\n", " output.clear_output()\n", " # セレクタで選択されているアイテムを使う\n", " print(f'選択されたファイル:{upload_selects.value}')\n", " print('これらのファイルをオブジェクトストレージへ保存します。問題ない場合は、次のセルへ進んでください。')\n", " print('選び直す場合は、再度ボックスから選択し、「決定」ボタンを押してください。')\n", " \n", "def on_click_callback_ALL(clicked_button: widgets.Button):\n", " with output:\n", " print('上のボックスに表示されている、全てのファイルをオブジェクトストレージへ保存します。\\n問題ない場合は、次のセルへ進んでください。')\n", " print('選び直す場合は、再度ボックスから選択し、「決定」ボタンを押してください。')\n", " upload_selects.value = data_files\n", "\n", "####################################################################################################\n", "####################################################################################################\n", "####################################################################################################\n", "\n", "print('どのデータをアップロードしますか?')\n", "print(' ◆◆◆ctrlキー(MAC:commandキー)を押しながらクリックすることで、複数データを選択できます◆◆◆')\n", "\n", "home_path = '/home/jovyan'\n", "annexed_data_paths = [os.path.join(home_path, 'input_data'), os.path.join(home_path, 'output_data')]\n", "data_files = []\n", "selects = []\n", "\n", "# 表示するボタン幅のデフォルト値\n", "default_width = '40%'\n", "\n", "# データフォルダの読み込み\n", "for data_path in annexed_data_paths:\n", " data_files += utils.fetch_files(data_path)\n", "\n", "data_files.sort()\n", "\n", "# upload_selects.valueの値を次のセルで処理の場合分けに利用する\n", "upload_selects = widgets.SelectMultiple(options=data_files, layout=Layout(width=default_width))\n", "button = widgets.Button(description='決 定', layout=Layout(width=default_width))\n", "button.on_click(on_click_callback)\n", "\n", "# 「すべてアップロードする」がクリックされたら全ファイルをupload_selectsに追加\n", "button_all = widgets.Button(description='すべてアップロードする', layout=Layout(width=default_width))\n", "button_all.on_click(on_click_callback_ALL)\n", "\n", "output = widgets.Output()\n", "\n", "display(upload_selects, button, button_all, output)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import papermill as pm\n", "\n", "upload_data_paths = list(upload_selects.value)\n", "\n", "index = 1\n", "for save_path in upload_data_paths:\n", " print(f'保存中です... ({index}/{len(upload_data_paths)})')\n", " pm.execute_notebook(\n", " './base_datalad_save_push.ipynb',\n", " '/home/jovyan/.local/push_log.ipynb',\n", " parameters = dict(SIBLING_NAME=special_remote_name, SAVE_MESSAGE='[GIN] データを保存', PATH=save_path, TO_GIT=False)\n", " )\n", " index += 1\n", "\n", "print('データのアップロードが完了しました。')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1-B. 実データをオブジェクトストレージから取得する\n", "\n", "この手順では、「0.オブジェクトストレージとの接続設定をする」で設定したオブジェクトストレージから、「git-annex」の管理下におかれた実データをダウンロードする際のサポートを提供します。\n", "\n", "以下のセルを順番に実行し、表示にしたがって操作することでデータをアップロードできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "import ipywidgets as widgets\n", "from ipywidgets import Layout\n", "from IPython.display import display\n", "\n", "from scripts import utils\n", "\n", "####################################################################################################\n", "########################################## callback functions ######################################\n", "####################################################################################################\n", "def on_click_callback(clicked_button: widgets.Button) -> None:\n", " with output:\n", " output.clear_output()\n", " # セレクタで選択されているアイテムを使う\n", " print(f'選択されたファイル:{download_selects.value}')\n", " print('これらのファイルをオブジェクトストレージから取得します。問題ない場合は、次のセルへ進んでください。')\n", " print('選び直す場合は、再度ボックスから選択し、「決定」ボタンを押してください。')\n", " \n", "def on_click_callback_ALL(clicked_button: widgets.Button):\n", " with output:\n", " print('上のボックスに表示されている、全てのファイルをオブジェクトストレージから取得します。\\n問題ない場合は、次のセルへ進んでください。')\n", " print('選び直す場合は、再度ボックスから選択し、「決定」ボタンを押してください。')\n", " download_selects.value = data_files\n", "\n", "####################################################################################################\n", "####################################################################################################\n", "####################################################################################################\n", "\n", "print('どのデータをダウンロードしますか?')\n", "print(' ◆◆◆ctrlキー(MAC:commandキー)を押しながらクリックすることで、複数データを選択できます◆◆◆')\n", "\n", "home_path = '/home/jovyan'\n", "annexed_data_paths = [os.path.join(home_path, 'input_data'), os.path.join(home_path, 'output_data')]\n", "data_files = []\n", "selects = []\n", "\n", "# 表示するボタン幅のデフォルト値\n", "default_width = '40%'\n", "\n", "# データフォルダの読み込み\n", "for data_path in annexed_data_paths:\n", " data_files += utils.fetch_files(data_path)\n", "\n", "data_files.sort()\n", " \n", "# download_selects.valueの値を次のセルで処理の場合分けに利用する\n", "download_selects = widgets.SelectMultiple(options=data_files, layout=Layout(width=default_width))\n", "button = widgets.Button(description='決 定', layout=Layout(width=default_width))\n", "button.on_click(on_click_callback)\n", "\n", "# 「すべてアップロードする」がクリックされたら全ファイルをdownload_selectsに追加\n", "button_all = widgets.Button(description='すべてダウンロードする', layout=Layout(width=default_width))\n", "button_all.on_click(on_click_callback_ALL)\n", "\n", "output = widgets.Output(layour={'border': '1px solid black'})\n", "\n", "display(download_selects, button, button_all, output)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Note: 前のセルからdownload_selects.valueを利用している\n", "download_data_paths = list(download_selects.value)\n", "\n", "index = 1\n", "for get_path in download_data_paths:\n", " print(f'データ取得中です... ({index}/{len(download_data_paths)})')\n", " !datalad get $get_path\n", " !datalad unlock $get_path\n", " index += 1\n", "\n", "print('実データのダウンロードが完了しました。')" ] } ], "metadata": { "language_info": { "name": "python" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }