オンラインストレージサービスの抽象化レイヤCosmosVFSの紹介

# はじめに
本記事では、筆者が開発しているオンラインストレージサービスの抽象化レイヤ、CosmosVFSとそのサブシステムであるAsteroidについて解説します.
筆者が独自に開発しているアプリケーションにすぎないCosmosVFSの解説記事をQiitaに投稿することには抵抗がありましたが、CosmosVFSを用いることでFTPなどの汎用プロトコルを用いて既存のオンラインストレージを利用できることから、他のアプリケーション開発者の実装基盤としてCosmosVFSを活用できると考え、本記事を投稿することにしました.
また、CosmosVFSはDBのBLOBフィールドを用いた仮想ファイルシステムを実装するなど、システムソフトウェアとしての独自性があるため、今後の類似アプリケーションの実装上の参考になればと考えました.


# CosmosVFSとは
![webifi-overview-image005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467445/f282b5fc-1db4-5898-e4cd-2d4def09bcb2.png)

CosmosVFSは筆者が開発しているオンラインストレージサービスの抽象化レイヤです.
CosmosVFSを用いることで、GoogleDriveやOneDrive、AmazonS3といったオンラインストレージサービスを単一のファイルツリーにマウントして、FTPやHTTP、9P2000でアクセスできるようになります.
既存のオンラインストレージのフロントエンドとして、汎用プロトコルであるFTPや9P2000を提供することで、Windowsのエクスプローラーやネットワークドライブ、Linuxのfuseといった、OSからのアクセシビリティ(OS透過性)が高いストレージ媒体として、オンラインストレージを利用することができます.
また、複数のオンラインストレージを仮想的なファイルツリーにマウントすることで、各ストレージの管理性が高まります.


[CosmosVFSのURL]
http://www.loxsols.com/pukiwiki/index.php?CosmosVFS


#Asteroidとは
AsteroidはCosmosVFSのサブシステムです.CosmosVFS自体はストレージの抽象化レイヤのため、仮想ファイルツリーを構成するためのディレクトリ以外は内部に何もデータを保持しませんが、サブシステムをマウントすることで、実ファイルを格納する空間を提供します.
例えば、AsteroidサブシステムをCosmosVFSにマウントすることで、独自のオンラインストレージを構築することが出来ます.Asteroidサブシステムは、1ユーザーあたり10GBのストレージを試験的に無料で提供します.

# CosmosVFSのアーキテクチャ
ここでは、CosmosVFSのアーキテクチャをフロントエンド、ミドルレイヤ、バックエンドに分けて解説します.

## フロントエンド(エンドポイント)
CosmosVFSのフロントエンド(エンドポイント)は、以下のプロトコルをサポートしています.
・FTP
・HTTP
・9P2000

CosmosVFSではフロントエンドをエンドポイントと呼称しています.
各エンドポイントは、それぞれ独自に実装したFTPサーバー、HTTPサーバー、9P2000サーバーとして提供されており、後述するミドルレイヤの仮想ファイルツリー上のファイルを配信します.

また、各エンドポイントは認証機能を備えており、CosmosVFS上で設定した任意のユーザー名/パスワードでログインすることができます.このユーザー名によって、仮想ファイルシステム上のどの部分木を配信するかを決定します.

エンドポイントに紐づいた任意のユーザーは、複数作成することができ、それぞれのユーザーがアクセスできるファイルツリーの部分木は別個のものを指定できるため、ユーザーごとに分離したファイルシステム空間を提供することが出来ます.
例えば、ユーザーAがアクセスできるファイルツリーはGoogleDriveだけとし、ユーザーBがアクセスできる空間はGoogleDriveとOneDriveを含むファイルツリーといったように、ユーザーごとにアクセス可能な範囲を分離することができます.

各エンドポイントは後述する仮想のファイルシステムを参照するため、CosmosVFSのサーバー上ではOSレベルのファイルシステムとしてはマウントされていません.
OSレベルのファイルシステムとして各ストレージをマウントしないことで、ユーザーごとの分離性とセキュリティを確保しています.


### FTPエンドポイント
FTPエンドポイントはCosmosVFSにマウントしたストレージを操作するためのFTPサーバーです.

### HTTPエンドポイント
HTTPエンドポイントはCosmosVFSにマウントしたストレージ上のファイルをHTTPで配信するためのWebサーバーです.

### 9P2000エンドポイント
9P2000エンドポイントはCosmosVFSにマウントしたストレージを操作するための9P2000サーバーです.


## ミドルレイヤ

CosomosVFSのミドルレイヤは、仮想ファイルシステムであるBLOBストレージ(Microsoft AzureのBLOBストレージではない)を実装しています.
BLOBストレージはRDBのBLOBフィールドの集合として実装しており、RDBの1レコードが仮想ファイルシステム上の1ファイルを構成しています.
仮想ファイルシステム上の各ファイルをRDBのレコードデータとして扱うことにより、ユーザーごとにファイル空間を分離し、ユーザー単位での管理の容易性を高めることができます.

<img width="147" alt="BLOBストレージ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467445/59fedb14-494f-cab6-ef7b-4d984bc5e1f6.png">

BLOBストレージを構成するBLOBフィールドには、実際のファイルを格納することができます.しかし、CosmosVFSでは後述するバックエンドに実ファイルを格納することを前提としており、一般ユーザーはBLOBストレージ上に実ファイルを格納できない仕様としています.この制限は、BLOBストレージのスケーラビリティがRDBを構成するデータファイルの容量制限に依存するため、あえて制限を設けています.
この制限のため、一般ユーザーはBLOBストレージ上にディレクトリだけを作成できます.
一方、CosmosVFSの特殊な権限をもったユーザーは、BLOBストレージ上に実ファイルを格納することができ、オンラインストレージの一種としてBLOBストレージを利用することができます.

## バックエンド
CosmosVFSのバックエンドは、実在するオンラインストレージをマウントするためのドライバ層として機能します.
このドライバ層では、以下のストレージのドライバを実装しています.
・GoogleDrive
・OneDrive
・AmazonS3
・ローカルストレージ(後述)
・サブシステム(後述)

CosmosVFSではユーザーごとにマウントできるストレージの種類を制限することができます.
例えば、ユーザーAはGoogleDriveやOneDriveといった公衆向けのオンラインストレージをマウントできるが、ユーザーBは後述するサブシステムだけをマウントすることにより、ユーザーBに対して外部へのデータ格納を制限することができます.
なお、現在のところ、CosmosVFSのサービスの実運用上は、全てのユーザーに対して、公衆向けのオンラインストレージのマウント権限を付与しています.
しかし、以下で述べるローカルストレージのマウント権限は外してあります.

### ローカルストレージ
ローカルストレージのドライバは、CosmosVFSを運用しているサーバー上のファイルシステムを利用するための機能を提供します.
ローカルストレージを利用することにより、管理者権限などを持った一部の特殊なユーザーは、サーバーの/procなどを参照して、サーバーの運用状況を把握することができます.
ローカルストレージによりマウントできる、実ファイルシステムの範囲は予め制限することができ、例えば/proc配下のファイルツリーだけをマウントする制限をかけることができます.
なお、セキュリティ上の理由により、CosmosVFSの一般ユーザーはローカルストレージのマウント権限を外してあります.

## サブシステム
<img width="358" alt="サブシステム.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467445/c5f59295-b684-8932-0401-03f9908850ac.png">

CosmosVFSのサブシステムは、バックエンドのストレージとしてマウントできる特殊なストレージ空間を提供しています.
例えば、AsteroidサブシステムはS3互換ストレージの上に、ユーザーごとに分離したファイルシステム空間を用意し、CosmosVFSのサブシステムドライバはその分離されたファイルシステム空間をマウントすることができます.
CosmosVFSとサブシステムの間のインターフェースは、ファイル転送は9P2000を採用し、管理用APIはSpringBootで実装したRestAPIを用いています.

管理用APIでは以下の機能を提供しています.
・サブシステムユーザーの作成
・サブシステムユーザーの削除
・サブシステムユーザーのパスワード変更
・サブシステムユーザーに付与されたストレージ容量の確認
・サブシステムユーザーに付与するストレージ容量の変更
・その他のプロパティの取得と変更

サブシステムユーザーは、CosmosVFSのユーザーとは別のサブシステム独自のユーザーを指します.
CosmosVFSとは別個のサブシステムユーザーを用意することで、将来的にサブシステム単体でサービスを提供することができるようにしています.
なお、現在のCosmosVFSの運用上は、サブシステムのユーザー名とCosmosVFSのユーザー名は同一の値しか設定できないようにし、また現在のところサブシステム単体でのサービス提供はしていません.

CosmosVFSとサブシステムの間のファイル転送は9P2000の汎用プロトコルを採用しています.ファイル転送にRestAPIを採用しなかったのは、将来ブロック型ストレージを提供するサブシステムを実装した場合に備えて、ランダムアクセスが可能なインターフェースを提供する必要性があったからです.

したがって、各サブシステムにはRestAPIを提供するWebサーバーの機能と、ファイル共有を行うための9P2000サーバーの機能を実装しています.


### Asteroidサブシステム
Asteroidサブシステムは、S3互換ストレージの単一バケットの中にユーザーごとに分離したファイルシステム空間を提供しています.
ユーザーごとに異なるS3バケットを確保することも検討しましたが、コスト上の理由により断念しました.
S3互換ストレージを採用したことにより、Asteroidは低廉なコストでユーザーに対してストレージを提供することができます.
この特性を利用して、2020年4月現在、1ユーザー当たり10GB使えるオンラインストレージを試験的に無料で提供しています.

## ユーザーインターフェース
<img width="252" alt="ストレージの追加画面.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467445/9f1fa2eb-d508-6db1-f4ff-309e0e8919d2.png">



CosmosVFSのユーザーインターフェースはWebアプリケーション(Javaサーブレット)として実装しており、warファイルに固めたうえでサーブレットコンテナでホストしています.
Springのような軽量フレームワークを採用しなかったのは、CosmosVFSがFTPや9P2000といったHTTP以外のプロトコルを扱うため、比較的自由度の高い実装方式を採用した方が、実装上問題が生じにくいと判断したためです.

CosmosVFSのユーザーインターフェースでは以下の機能を提供しています.
・ストレージのマウント/アンマウント
・エンドポイントの作成/廃棄
・エンドポイント単位でのユーザー作成
・サブシステムの有効化/無効化
・マウントしたストレージのブラウズとファイルの参照

CosmosVFSのユーザーは、エンドポイントのユーザーとは別個のものを採用しており、現在のところ、GoogleIDと連携して取得したメールアドレスを採用しています.
ただし、CosmosVFSの内部にユーザー情報を保持するテーブルを用意しており、将来的にGoogleID以外の手段でユーザーを作成することができるようになっています.

## Net2FTP2Cosmnos

<img width="480" alt="net2ftp2cosmos.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467445/c65d32fc-4771-a6b2-3eec-865105296da3.png">

[Net2FTP2CosmnosのURL]
https://www.cosmos-vfs.com/net2ftp2cosmos/

Net2FTP2Cosmosは、Webブラウザ上で動作するFTPクライアントです.OSSのNet2FTPをベースに実装しました.
Net2FTP2Cosmosを利用することで、CosmosVFSで作成したFTPエンドポイントをWebブラウザ上から操作することができます.

### Cosmos9P2KClient

<img width="361" alt="Cosmos9P2KClient-20200413-003.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467445/6cf86790-8eec-a40d-9617-f995e1a6781d.png">

[Cosmos9P2KClientのURL]
http://www.loxsols.com/pukiwiki/index.php?Cosmos9P2KClient

Cosmos9P2KClientは、C#で実装した9P2000のGUIクライアントです.
9P2000サーバー上のファイルをGUIでブラウズし、ドラッグ&ドロップでファイルをアップロードしたりすることができます.
Cosmos9P2KClientは、CosmosVFSの9P2000エンドポイントの検証のために実装しました.


# 実装上の工夫点
CosmosVFSの実装にあたっては以下の点に留意しました.

## ユーザーごとの分離性
セキュリティ上の理由により、ユーザーごとにファイルシステム空間を強く分離することを志向しました.
具体的には、
・ユーザーのストレージ空間をOSレベルでマウントしないこと
・ユーザーの仮想ファイルツリー全体を単一のツリーに集約しないこと
・RDBに対するSQL操作だけでユーザーのファイルシステム空間を解放できること
を実現しています.

## RDBを用いた管理容易性
仮想ファイルツリーは、RDBのBLOBフィールドを応用したBLOBストレージとして実装しました.
仮想ファイルツリーをRDB上に構築することで、ユーザ単位でファイルツリーを分離しつつ、管理の容易性を確保しています.
たとえば、あるユーザーに紐づくBLOBストレージ上のファイルやディレクトリの一覧を取得する場合は、単一のSQL文を実行することで実現できます.
また、ユーザーがどんなストレージをマウントし、どんなエンドポイントでファイルを共有しているかも管理用画面で参照できるようにしています.これらの管理用画面もまた、RDBに対するSQL文を実行することで実現できます.

CosmosVFSの下層で動作するRDBにはHSQLDBを採用しています.これはCosmosVFSの開発段階では組み込みDBとして機能し、実運用時はサーバーモードで動作するRDBを要件として求めた結果です.

## ユーザーモードで処理が完結すること
各ストレージのマウントにあたっては、CosmosVFSが動作するマシンのOSレベルでマウントしないように設計しました.
各ストレージのマウントとアンマウントの操作は、ユーザーモードアプリケーションのメモリ空間の中で、仮想のファイルツリーに対する操作を行うことで実現しています.
OSレベルでストレージをマウントしないことで、ユーザーごとに分離されたファイルシステム空間を確保しています.
したがって、CosmosVFSは純粋なユーザーモードアプリケーションとしてJavaで実装しています.結果、CosmosVFSはWindowsでもLinuxでも動作するマルチプラットフォームのアプリケーションとして仕上がっています.

## 拡張性があること
CosmosVFSは様々なストレージをマウントし、様々なエンドポイントでファイルを共有できるようにするため、モジュラリティを確保した実装を行っています.
具体的には、各ストレージをドライバ層で抽象化し、エンドポイントの実装にあたってはJavaのスーパークラスに対する共通の操作として実装しています.
このほか、ルートファイルシステムとして仮想ファイルシステムであるBLOBストレージを採用したり、サブシステムをマウントすることで機能を拡張できるようにして拡張性を確保しています.





# 性能測定
※ 筆者の環境の制約で、広帯域回線が確保できていないため、本格的な性能測定は実施していません.今後実施する予定です.



# 今後の展開
CosmosVFSの今後の展開として以下の機能の実装を予定しています.

## エンドポイントの拡充
NFSやWebSocketを用いたエンドポイントの実装を予定しています.

## サブシステムの拡充
以下のような特殊なファイルシステムの実装を予定しています.

### 特殊な機能を持ったファイルシステム
・PDFファイルをアップロードすると画像に変換するファイルシステム

### プッシュ型のオンラインストレージ
9P2000のサーバーとクライアントの役割を逆転させて、クライアントのストレージ空間をプッシュ型で配信できるファイルシステムの実装を検討しています.

# まとめ
本記事では、オンラインストレージサービスの抽象化レイヤであるCosmosVFSと、そのサブシステムであるAsteroidについての紹介と、アーキテクチャの解説を行いました.
CosmosVFSを利用することで、既存のオンラインストレージをFTPなどの汎用プロトコルから利用できるようになるため、他のアプリケーション開発者の方がファイルアクセスのための基盤として利用できると考えます.
また、CosmosVFSは独自に実装したBLOBストレージなど、システムソフトウェアとして独自性のあるアーキテクチャで構成されているため、本記事が他の類似アプリケーションを実装する上での参考資料になると考えて執筆しました.