IBM Cloud Functions を使って IBM Cloud Object Storage (ICOS) に直接ファイルダウンロード


# はじめに

サイズが大きいイメージファイルなどを IBM Cloud Object Storage (ICOS) に直接ファイルダウンロードしたいことがあります。
一旦、ローカルPCにダウンロードしてから IBM Cloud Object Storage (ICOS) にアップロードすると、ローカルPCが接続された回線にも依存し、時間がかかることがあります。
今回は、URL 先のファイルをローカルPCに保存せず IBM Cloud Object Storage (ICOS) に直接ファイルダウンロードする機能を IBM Cloud Functions を使って実装します。

AWS Lamda の場合は `/tmp` ディレクトリのストレージサイズが 512 MB という制限がありますが、IBM Cloud Functions の場合、`/tmp` ディレクトリのストレージサイズに明確な制限は設けていないので、GB 級のファイルにも対応できます。

>[AWS Lambda の制限 - AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-limits.html)
>
| リソース      |       制限|  
|:-----------------|------------------:|
| `/tmp` ディレクトリのストレージ |512 MB |

# 作成イメージ
IBM Cloud Functions からは IBM Cloud Object Storage (ICOS) のプライベートエンドポイントを利用してアップロードします。

![Kobito.frv4WL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/3695b0e6-5aec-70ae-5f87-8cb148e6d819.png "Kobito.frv4WL.png")


# 事前準備

## GitHub からダウンロード
GitHub にあるファイルをダウンロードします。

>[khayama/fn-dl2cos: IBM Cloud Function to download a file and upload to IBM Cloud Object Storage](https://github.com/khayama/fn-dl2cos)

```
git clone https://github.com/khayama/fn-dl2cos.git
cd fn-dl2cos
```

今回の Functions デプロイ用 yaml では以下のように定義しています。
Functions 実行パラメータは、環境変数の値を取得して埋め込む形で定義しています。

```yaml:dl2cos_action.yml
packages:
  dl2cos_package:
    version: 1.0
    license: Apache-2.0
    actions:
      dl2cos:
        version: 1.0
        description: IBM Cloud Function to download a file and upload to IBM Cloud Object Storage
        runtime: python@3
        function: dl2cos_code.py
        limits:
          timeout : 300000
          memorySize : 1024
        inputs:
          COS_ENDPOINT : $COS_ENDPOINT
          COS_API_KEY_ID : $COS_API_KEY_ID
          COS_RESOURCE_CRN : $COS_RESOURCE_CRN
          COS_BUCKET_LOCATION : $COS_BUCKET_LOCATION
          URL : $URL
```

>- [openwhisk-wskdeploy/spec_actions.md at master · apache/openwhisk-wskdeploy](https://github.com/apache/openwhisk-wskdeploy/blob/master/specification/html/spec_actions.md#actions)
>- [openwhisk-wskdeploy/spec_trigger.md at master · apache/openwhisk-wskdeploy](https://github.com/apache/openwhisk-wskdeploy/blob/master/specification/html/spec_trigger.md)
>- [openwhisk-wskdeploy/spec_rule.md at master · apache/openwhisk-wskdeploy](https://github.com/apache/openwhisk-wskdeploy/blob/master/specification/html/spec_rule.md)

## `ibmcloud` コマンド準備
コマンドで使う変数を定義します。

```
export REGION="jp-tok"
export RESOURCE_GROUP="khayama-rg"
```

`ibmcloud` コマンドでログインし、プラグインをインストールします。

```
ibmcloud login -a cloud.ibm.com -r $REGION -g $RESOURCE_GROUP 
ibmcloud plugin install cloud-functions
```

# Functions デプロイ

## Functions namespace 作成
`namespace` を作成してプロパティをセットします。

```
ibmcloud fn namespace create khayama-fn
ibmcloud fn namespace target khayama-fn
```

## 環境変数セット
以下のように環境変数をセットします。

```
export COS_ENDPOINT="https://s3.private.jp-tok.cloud-object-storage.appdomain.cloud" # 保存したい先の IBM Cloud Object Storage バケットがあるリージョンのエンドポイント
export COS_API_KEY_ID="W00YiRnLW4a3fTjMB-odB-2ySfTrFBIQQWanc--P3byk" # IBM Cloud Object Storage サービス認証情報の <api-key> 
export COS_RESOURCE_CRN="crn:v1:bluemix:public:cloud-object-storage:global:a/3bf0d9003abfb5d29761c3e97696b71c:d6f04d83-6c4f-4a62-a165-696756d63903::" # IBM Cloud Object Storage サービス認証情報の <resource-instance-id>
export COS_BUCKET_LOCATION="khayama-bucket" # 保存したい先の IBM Cloud Object Storage バケット名
export URL="http://ipv4.download.thinkbroadband.com/5MB.zip" # ダウンロードしたファイルの URL (あとから上書き実行可能）
```

>[Initializing configuration](https://cloud.ibm.com/docs/services/cloud-object-storage?topic=cloud-object-storage-python&locale=dk#python-examples-init)
> • \<api-key\> - api key generated when creating the service credentials (write access is required for creation and deletion examples)
> • \<resource-instance-id\> - resource ID for your cloud Object Storage (available through IBM Cloud CLI or IBM Cloud Dashboard)
![Kobito.nmv9yw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/370c612a-3970-9af4-90fd-58fc899424c7.png "Kobito.nmv9yw.png")


## yaml ファイルを指定してデプロイ
これで Functions の Action を一発でデプロイできます。

```
ibmcloud fn deploy --manifest dl2cos_action.yml
--> Success: Deployment completed successfully.
```

作成されたかどうかの確認するコマンドです。

```
ibmcloud fn package list
ibmcloud fn action list
```

# `dl2cos` アクション実行

作成した Functions を実行し結果を確認します。 
`true` と返ってくれば成功です。

```
ibmcloud fn action invoke dl2cos_package/dl2cos --result

{
    "message": true
}

```

以下のコマンドで直近のアクションに関するログを確認できます。
5 MB のファイルを 16 秒で IBM Cloud Object Storage (ICOS) に直接ファイルダウンロードできたことがわかります。
`ResourceWarning` については無視してください。

```
ibmcloud fn activation get -l | grep duration && ibmcloud fn activation get -lg

    "duration": 16354,
File name : 5MB.zip
Content-Type : application/zip
Download file completed.
Upload file to COS completed.
/action/1/src/exec__.py:66: ResourceWarning: unclosed <ssl.SSLSocket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('192.168.2.110', 40642), raddr=('10.1.129.66', 443)>
res = main(payload)
ResourceWarning: Enable tracemalloc to get the object allocation traceback
```

他の URL を指定してダウンロードしたい場合は、以下のコマンドを実行します。
GB 級のファイルだと少し時間がかかることがあります。

```
ibmcloud fn action invoke dl2cos_package/dl2cos --result --param URL "http://ftp.riken.jp/Linux/centos/7.7.1908/isos/x86_64/CentOS-7-x86_64-DVD-1908.iso"
ok: invoked /_/dl2cos_package/dl2cos, but the request has not yet finished, with id 61b20a0014f0441ab20a0014f0f41aef
```

4.3 GB のイメージファイルも 62 秒で IBM Cloud Object Storage (ICOS) に直接ファイルダウンロードできたことがわかります。

```
ibmcloud fn activation get -l | grep duration && ibmcloud fn activation get -lg

    "duration": 62984,
File name : CentOS-7-x86_64-DVD-1908.iso
Content-Type : application/x-iso
Download file completed.
Upload file to COS completed.
```

# `dl2cos` アクション削除

作成した Functions の Action を一発で削除するには、こちらのコマンドでできます。


```
ibmcloud fn undeploy --manifest dl2cos_action.yml
--> Success: Undeployment completed successfully.
```

# さいごに
これで、ローカルPCを経由せずに IBM Cloud Object Storage (ICOS) に直接ファイルダウンロードする仕組みがつくれました。
クラウドにイメージファイルを持ち込みたいときなどは便利なので活用してください。

# 参考リンク

- [Using Python](https://cloud.ibm.com/docs/services/cloud-object-storage/libraries?topic=cloud-object-storage-python)
- [Download Test Files | thinkbroadband](https://www.thinkbroadband.com/download)
- [Download large file in python with requests - Stack Overflow](https://stackoverflow.com/questions/16694907/download-large-file-in-python-with-requests)
- [Index of /Linux/centos/7.7.1908/isos/x86_64](http://ftp.riken.jp/Linux/centos/7.7.1908/isos/x86_64/?C=S;O=A)