IBM Cloud Object Storage (ICOS) を vSphere Content Library として Subscribe 利用する

# vSphere Content Library とは
OVF テンプレートや ISO ファイルをライブラリ化してvCenter 単位で管理し、他の vCenter サイトにも公開できるといったものです。

>[コンテンツ ライブラリの使用](https://docs.vmware.com/jp/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-254B2CE8-20A8-43F0-90E8-3F6776C2C896.html)
コンテンツ ライブラリは、仮想マシン テンプレートおよび vApp テンプレートに加えて、ISO イメージ、テキスト ファイルなどの他のファイル タイプのコンテナ オブジェクトです。ライブラリ内のテンプレートを使用して、vSphere インベントリに仮想マシンと vApp をデプロイできます。コンテンツ ライブラリを使用して、同じ場所または異なる場所の vCenter Server インスタンス間でコンテンツを共有することもできます。テンプレートとファイルを共有すると、ワークロードの大規模なデプロイで整合性やコンプライアンスを確保し、デプロイを効率化および自動化できます。

>[vSphere Content Library: distribute your content](https://blogs.vmware.com/vsphere/2015/08/vsphere-content-library-distribute-your-content-effortlessly.html)
![vSphere Content Library](https://blogs.vmware.com/vsphere/files/2015/08/map-final.png)

# 概要
通常、Content Library の作成には vCenter が必要ですが、
今回は 「[Create a vCenter Content Library using AWS S3 - Part 2](http://www.gilles.cloud/2018/07/create-vcenter-content-library-using.html)」を参考にして、
IBM Cloud Object Storage (ICOS) だけで Content Library を無理やり（？）仕立てて試します。
ICOS を使うことで、作業用サーバーや vSphere データストアのストレージを圧迫することなく、必要なときだけダウンロードする構成がとれます。
また、Private Endpoint を経由することで ICOS からのアウトバウンドデータ通信も課金されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/44f2942f-c3f5-9e3f-da32-cb89659c4950.png)

# ICOS 準備
CLI を使って構成準備を進めます。

## `ibmcloud` ログイン

```shell:

export REGION="jp-tok"
export RESOURCE_GROUP="khayama-rg"
ibmcloud login -a cloud.ibm.com -r $REGION -g $RESOURCE_GROUP
```

## ICOS サービスインスタンス作成

```shell:

export COS_NAME=khayama-cos
export COS_PLAN=standard

ibmcloud resource service-instance-create $COS_NAME \
cloud-object-storage $COS_PLAN global
```

## CLI プラグインインストール

```shell:

ibmcloud plugin install cloud-object-storage
ibmcloud plugin show cloud-object-storage
```

## ICOS バケットの作成
`jp-tok` に Smart Tier のバケットを作成します。

```shell:

export BUCKET_NAME=content-library

export COS_ID=$(ibmcloud resource service-instance --output JSON $COS_NAME | jq -r '.[].id')
echo $COS_ID

ibmcloud cos config region $REGION
ibmcloud cos config crn $COS_ID

ibmcloud cos create-bucket \
--bucket $BUCKET_NAME --class smart
```

## ICOS サービス認証情報の作成
Content Library 設定に必要な認証情報を作成します。

```shell:

ibmcloud resource service-key-create "$COS_NAME"-service-key  --instance-id $COS_ID --parameters '{"HMAC":true}'
ibmcloud resource service-keys  
```

その認証情報を使って `config` と `credentials` ファイルを作成します。

```shell:

ACCESS_KEY_ID=$(ibmcloud resource service-key "$COS_NAME"-service-key --output json | jq -r '.[]|.credentials.cos_hmac_keys.access_key_id')
echo $ACCESS_KEY_ID

SECRET_ACCESS_KEY=$(ibmcloud resource service-key "$COS_NAME"-service-key --output json | jq -r '.[]|.credentials.cos_hmac_keys.secret_access_key')
echo $SECRET_ACCESS_KEY

cat <<EOF > ~/.aws/config 
[default]
region = $REGION
EOF

cat <<EOF > ~/.aws/credentials 
[default]
aws_access_key_id = $ACCESS_KEY_ID
aws_secret_access_key = $SECRET_ACCESS_KEY
EOF
```

# ファイルアップロード
OVF テンプレートと ISO ファイルをアップロードし、以下のような構成とします。

```shell:

% ibmcloud cos objects --bucket $BUCKET_NAME                                          
OK
見つかりました 8 バケットにオブジェクトがあります 'content-library':

名前                                            最終変更日時               オブジェクト・サイズ   
iso/                                            Sep 28, 2020 at 12:38:41   0 B   
iso/groovy-desktop-amd64.iso                    Sep 28, 2020 at 13:00:47   2.77 GiB   
iso/windows_server_2019_EVAL_x64FRE_ja-jp.iso   Sep 29, 2020 at 07:44:02   5.17 GiB   
photon-hw11-3.0-a383732/                        Sep 29, 2020 at 14:03:33   0 B   
photon-hw11-3.0-a383732/photon-ova-disk1.vmdk   Sep 29, 2020 at 14:03:39   187.80 MiB   
photon-hw11-3.0-a383732/photon-ova.cert         Sep 29, 2020 at 14:03:39   1.86 KiB   
photon-hw11-3.0-a383732/photon-ova.mf           Sep 29, 2020 at 14:03:39   133 B   
photon-hw11-3.0-a383732/photon-ova.ovf          Sep 29, 2020 at 14:03:39   36.42 KiB     
```

# GitHub からスクリプトをダウンロード
AWS S3 用に作られたスクリプトを IBM Cloud Object Storage (ICOS) 用にカスタマイズできます。

- [khayama/vghetto-scripts: Various virtuallyGhetto scripts for VMware based solutions](https://github.com/khayama/vghetto-scripts)

```
git clone https://github.com/khayama/vghetto-scripts.git
cd vghetto-scripts
```

必要に応じて、この部分を変更してください。

```
% cat make_vcsp_2018_ibmcos.py | grep COS_ENDPOINT
    COS_ENDPOINT = "https://s3.jp-tok.cloud-object-storage.appdomain.cloud"
    s3 = ibm_boto3.resource("s3",endpoint_url=COS_ENDPOINT)
    s3_client = ibm_boto3.client("s3",endpoint_url=COS_ENDPOINT)
```

# python スクリプト実行
ICOS 用のライブラリをインストールして、python スクリプトを実行します。

```
python3 -m pip install -U ibm-cos-sdk
python3 make_vcsp_2018_ibmcos.py -n ibmcos-private-content-library -t s3 -p $BUCKET_NAME
```

以下のように、 `lib.json`、 `items.json`、 `xxx/item.json` が作成されたことが確認できます。

```
% ibmcloud cos objects --bucket $BUCKET_NAME
OK
見つかりました 13 バケットにオブジェクトがあります 'content-library':

名前                                                  最終変更日時               オブジェクト・サイズ   
iso/                                                  Sep 28, 2020 at 12:38:41   0 B   
iso/groovy-desktop-amd64.iso                          Sep 28, 2020 at 13:00:47   2.77 GiB   
iso/groovy-desktop-amd64/item.json                    Sep 29, 2020 at 15:21:38   536 B   
iso/windows_server_2019_EVAL_x64FRE_ja-jp.iso         Sep 29, 2020 at 07:44:02   5.17 GiB   
iso/windows_server_2019_EVAL_x64FRE_ja-jp/item.json   Sep 29, 2020 at 15:21:38   604 B   
items.json                                            Sep 29, 2020 at 15:21:38   2.89 KiB   
lib.json                                              Sep 29, 2020 at 15:21:38   342 B   
photon-hw11-3.0-a383732/                              Sep 29, 2020 at 14:03:33   0 B   
photon-hw11-3.0-a383732/item.json                     Sep 29, 2020 at 15:21:38   1.39 KiB   
photon-hw11-3.0-a383732/photon-ova-disk1.vmdk         Sep 29, 2020 at 14:03:39   187.80 MiB   
photon-hw11-3.0-a383732/photon-ova.cert               Sep 29, 2020 at 14:03:39   1.86 KiB   
photon-hw11-3.0-a383732/photon-ova.mf                 Sep 29, 2020 at 14:03:39   133 B   
photon-hw11-3.0-a383732/photon-ova.ovf                Sep 29, 2020 at 14:03:39   36.42 KiB   
```
# ICOS IP Firewall 設定
Private Endpoint を経由したアクセスを想定していますが、特定のソースIPに絞ったアクセスを設定します。

> - [Setting a firewall - Set a firewall through an API](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-setting-a-firewall#firewall)
> - [COS Resource Configuration API - Make changes to a bucket's configuration.](https://cloud.ibm.com/apidocs/cos/cos-configuration#updatebucketconfig)


- `$(curl http://checkip.amazonaws.com)` は現在のアクセス元グローバルIPを表しますが、オプションです。入れておくと UI アクセス時にも拒否されないので便利です。
- `10.212.20.64/26` は vCenter を含む vSphere 管理系セグメントです。

```shell:

BUCKET_NAME=content-library

export ACCESS_TOKEN=$(ibmcloud iam oauth-tokens --output JSON | jq -r '.iam_token')
echo $ACCESS_TOKEN

curl -X PATCH https://config.cloud-object-storage.cloud.ibm.com/v1/b/$BUCKET_NAME -H "authorization: $ACCESS_TOKEN" -d @- << EOF
{
  "firewall": {
    "allowed_ip": [
      "$(curl http://checkip.amazonaws.com)",
      "10.212.20.64/26"
    ]
  }
}
EOF

curl https://config.cloud-object-storage.cloud.ibm.com/v1/b/$BUCKET_NAME -H "authorization: $ACCESS_TOKEN" | jq -r
```

# ICOS Public Access を有効化
バケットに対して Public Access を有効化し、 Anonymous アクセスを許可します。
その上で、先ほど設定した IP Firewall により Private の vSphere 管理セグメントからのアクセスに限定できます。

- [Managing public access to resources - Assigning access by using the API](https://cloud.ibm.com/docs/account?topic=account-public#public-access-api)

```shell:

export COS_NAME=khayama-cos
export BUCKET_NAME=content-library

export ACCOUNT_ID=$(ibmcloud account show --output json | jq -r '.account_id')
echo $ACCOUNT_ID

export COS_INSTANCE_ID=$(ibmcloud resource service-instance --output JSON $COS_NAME | jq -r '.[].guid')
echo $COS_INSTANCE_ID

export ACCESS_TOKEN=$(ibmcloud iam oauth-tokens --output JSON | jq -r '.iam_token')
echo $ACCESS_TOKEN

curl -X POST \
"https://iam.cloud.ibm.com/v1/policies" \
-H "Authorization: $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d @- << EOF
{
  "type": "access",
  "subjects": [
    {
      "attributes": [
        {
          "name": "access_group_id",
          "value": "AccessGroupId-PublicAccess"
        }
      ]
    }
  ],
  "roles": [
    {
      "role_id": "crn:v1:bluemix:public:cloud-object-storage::::serviceRole:ContentReader"
    }
  ],
  "resources": [
    {
      "attributes": [
        {
          "name": "accountId",
          "value": "$ACCOUNT_ID",
          "operator": "stringEquals"
        },
        {
          "name": "serviceName",
          "value": "cloud-object-storage",
          "operator": "stringEquals"
        },
        {
          "name": "serviceInstance",
          "value": "$COS_INSTANCE_ID",
          "operator": "stringEquals"
        },
        {
          "name": "resourceType",
          "value": "bucket",
          "operator": "stringEquals"
        },
        {
          "name": "resource",
          "value": "$BUCKET_NAME",
          "operator": "stringEquals"
        }
      ]
    }
  ]
}
EOF
```

# vSphere Client から Content Library を登録
以下の画面のように進めます。

![貼り付けた画像_2020_09_29_17_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a44ce4e2-5748-2b93-3329-d4b44a984393.png "貼り付けた画像_2020_09_29_17_19.png")
![貼り付けた画像_2020_09_29_17_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/cc2da6ee-df70-bece-8acf-b1fe9771617e.png "貼り付けた画像_2020_09_29_17_20.png")

↓適当な名前を入力してください。

![Kobito.h2YXNc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/0b6bfc39-4750-8738-fcf2-0f7e5cda601c.png "Kobito.h2YXNc.png")

↓ `https://$BUCKET_NAME.$ENDPOINT/$OBJECT_NAME` の形式で `lib.json` を指定します。

![Kobito.VIy2E9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/ddbde056-8791-1091-50cc-a51dacffed82.png "Kobito.VIy2E9.png")

↓続行します。

![Kobito.zchGI5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/4f217d47-ce8f-2a75-0ab4-49841a49ca29.png "Kobito.zchGI5.png")

↓保管先ストレージを指定します。

![Kobito.5j7GOd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/123fbd68-5d94-1c70-eeee-e30455a6d380.png "Kobito.5j7GOd.png")

↓以上で完了です。

![Kobito.RhRILn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/5b83bf45-9736-adcd-7459-c3f1c20fa327.png "Kobito.RhRILn.png")

↓このように登録が確認できました。

![Kobito.UV9qrR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/ec2f325d-fdee-a84a-115c-2c970ec6aa41.png "Kobito.UV9qrR.png")

# 稼働確認
以下のように、ISO ファイルと OVF テンプレートについて、ぞれぞれ必要に応じてアイテムを同期・削除できることが確認できました。

![貼り付けた画像_2020_09_29_17_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/59b07771-b802-e55b-f7f0-490234aa4e31.png "貼り付けた画像_2020_09_29_17_34.png")
![貼り付けた画像_2020_09_29_17_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/aa079897-5076-b4da-c110-ae14919d014a.png "貼り付けた画像_2020_09_29_17_36.png")
![貼り付けた画像_2020_09_29_23_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/0260952f-74fe-73a6-48ec-c0cc8a3b7d96.png "貼り付けた画像_2020_09_29_23_11.png")

# さいごに

以下が考慮すべき点と思いますが、1 回作っておけば、かなり便利に構築作業を進められると思います。

- ICOS にファイルアップロードしてコンテンツ追加を反映するためには、python スクリプトを走らせてから Content Library で同期をかけることが必要
- OVA ファイルはそのまま認識されないため、展開した（.ovf 等を含む）フォルダをアップロードする必要がある

# その他、参考

- [VMwareのコンテンツライブラリを使用して複数環境でテンプレートを共有してみた - Qiita](https://qiita.com/ytada/items/5d67c7e5a8f96c7c674b)
- [Using Python](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-python)