ConoHaのVMでUbuntu 14.04を使ってs3qlでSwift Object Storageをマウントする

追記: この記事は[ConoHa Advent Calendar 2015](http://qiita.com/advent-calendar/2015/conoha)の記事となります。

修正1(2015/12/14 18:00): openstack server create ... のコマンドで、instance_name_tag=を指定するところを'"(ダブルクオート)'でくくるように表記を変えました。シングルクオートだと、\u2018 \u2019のunicodeのクオートに表示がなっていたみたいで、紛らわしいので修正。

修正2(2015/12/21 16:00): swiftks storage urlの指定方法について、別記事で指摘がありました。独自ドライバを作らなくても良いみたいですので、こちらを見てstorage urlを設定してみてください。(http://qiita.com/hikaru_uchiyama/items/504b7e5e75f747c12366)

「ConoHaのVMでUbuntu 14.04を使ってs3qlでSwift Object Storageをマウントする」というタイトルなんですけど、なんでs3qlとかいうと、このfuseマウントの特徴は、下記の感じになります。

**pros**
  - 最新版はpython3ベースで動く
  - tLarge fileをサポートしている
  - 書き込み、読み込みキャッシュをするので基本的にマウントする環境(cache)のdiskの速度に依存する
  - 後で中身を実際に見ますが、オブジェクトはs3qlのdata形式で転送されるので、中身はマウントしないとわからない
  - マウントしている環境のcacheやencryptの仕組みに依存するので、複数のサーバでのマウントをサポートしていない(自分は未検証、仕組み的に同時に書き込んだりはできないことはわかる)
  - マウントした領域をCIFSとかFTPで共有すことでgatewayとして利用できる

**cons**
  - cacheやメタデータの処理をapswとsqlite3に依存しているので、このデータを保存しているホストでしかマウントできない
    - (s3ql自体が、複数台構成やHA構成などを考慮していない? メタデータのバックアップ、リストアで復元可能かどうか要検討)

ということで、初日に hironobu_s さんがSwiftFsとは別のメリット、デメリットが有ります。

CIFS領域としてsambaで共有して、ファイルサーバのgatewayとして使うには良いかんじです。
(keystoneとsambaがユーザ情報共有している環境など、工夫して、sambaのユーザのhome dirでpreexecとかすると、ユーザごとにアカウントのswiftをマウントするとかできそうな気もします)

他にもgatewayとしてswiftに対して動作するものはありますが、cacheするopensource実装はほとんど無いですね。s3ql + sambaみたいに使うのは動作の軽さも含めてすごく合理的です。

手前味噌ですが、vmつくるところの詳しくは、gihyo.jpの私の記事とかをみてもらってもいいかも。
http://gihyo.jp/dev/serial/01/conoha/0005
第5回　OpenStack APIを使ったCLI操作をConoHaでやってみる

以下、手順といった感じを記載します。

# s3ql環境構築とインストール

べつにCentOS 6.7とかでも良いんですけど、python3の環境を作りやすく、パッケージでインストールしやすいUbuntu 14.04をつかいます。

## openstackコマンドでimage listでubuntu 14.04をさがす
OSのイメージファイルの確認をします。

```bash:shell
$ openstack image list -f csv 2>/dev/null | grep ubuntu
"ee695cb6-10dc-447d-8c97-f0bc54750e44","vmi-docker-1.8-ubuntu-14.04"
"ae6c182a-27e8-43d4-b36d-fabe2eb016f1","vmi-ubuntu-12.04-i386"
"e31d6093-afe9-41d0-a958-c21da36141fb","vmi-ubuntu-12.04-amd64"
"0477b6db-ef5b-4fa9-8ce7-ce85773425cd","vmi-ubuntu-14.04-i386"
"a87dfe9f-a8a4-4634-9a40-dbeba7ee7013","vmi-ubuntu-14.04-amd64"
"b3b42464-01c0-49bb-b360-ad4f46024775","vmi-drone-0.3-ubuntu-14.04"
```

ubuntu 14.04の amd64 とか選択します

## vmつくるので、flavor list (1gbでいいよね)
作成するプランの確認をします

```bash:shell
$ openstack flavor list -f csv 2>/dev/null

"ID","Name","RAM","Disk","Ephemeral","VCPUs","Is Public"
"294639c7-72ba-43a5-8ff2-513c8995b869","g-2gb",2048,50,0,3,True
"3aa001cd-95b6-46c9-a91e-e62d6f7f06a3","g-16gb",16384,50,0,8,True
"62e8fb4b-6a26-46cd-be13-e5bbf5614d15","g-4gb",4096,50,0,4,True
"7eea7469-0d85-4f82-8050-6ae742394681","g-1gb",1024,50,0,2,True
"965affd4-d9e8-4ffb-b9a9-624d63e2d83f","g-8gb",8192,50,0,6,True
"a20905c6-3733-46c4-81cc-458c7dca1bae","g-32gb",32768,50,0,12,True
"c2a97b05-1b4b-4038-bbcb-343201659279","g-64gb",65536,50,0,24,True
```

## さきにセキュリティグループを作っておく
外からは、sshだけで良いのでssh接続を許可するセキュリティ設定を作ります。
コマンドだけ貼ります。

ingress tcp port 22を許可します。

```bash:shell
$ neutron security-group-create ssh-works --description "allow ssh connect"

$ neutron security-group-rule-create --direction ingress --ethertype IPv4 \
  --protocol tcp --port-range-min 22 --port-range-max 22 ssh-works -f value
```

確認(無理にyamlで出力w)

```bash:shell
$ neutron security-group-show ssh-works -f yaml
- {Field: description, Value: allow ssh connect}
- {Field: id, Value: 8ac76c8f-f4b6-4cdf-972c-1c01feadef9e}
- {Field: name, Value: ssh-works}
- {Field: security_group_rules, Value: "{\n     \"remote_group_id\": null, \n    \
    \ \"direction\": \"ingress\", \n     \"remote_ip_prefix\": null, \n     \"protocol\"\
    : \"tcp\", \n     \"tenant_id\": \"aefde53ff77d4c8bba639b26ccff55fc\", \n    \
    \ \"port_range_max\": 22, \n     \"security_group_id\": \"8ac76c8f-f4b6-4cdf-972c-1c01feadef9e\"\
    , \n     \"port_range_min\": 22, \n     \"ethertype\": \"IPv4\", \n     \"id\"\
    : \"0c60065e-7ca1-47a3-9d50-4f907cbba0a3\"\n}\n{\n     \"remote_group_id\": null,\
    \ \n     \"direction\": \"egress\", \n     \"remote_ip_prefix\": null, \n    \
    \ \"protocol\": null, \n     \"tenant_id\": \"aefde53ff77d4c8bba639b26ccff55fc\"\
    , \n     \"port_range_max\": null, \n     \"security_group_id\": \"8ac76c8f-f4b6-4cdf-972c-1c01feadef9e\"\
    , \n     \"port_range_min\": null, \n     \"ethertype\": \"IPv4\", \n     \"id\"\
    : \"2eb23b65-e3f7-48bf-bfc4-2ef04d93d014\"\n}\n{\n     \"remote_group_id\": null,\
    \ \n     \"direction\": \"egress\", \n     \"remote_ip_prefix\": null, \n    \
    \ \"protocol\": null, \n     \"tenant_id\": \"aefde53ff77d4c8bba639b26ccff55fc\"\
    , \n     \"port_range_max\": null, \n     \"security_group_id\": \"8ac76c8f-f4b6-4cdf-972c-1c01feadef9e\"\
    , \n     \"port_range_min\": null, \n     \"ethertype\": \"IPv6\", \n     \"id\"\
    : \"887e34da-760a-4739-bdd6-b2bd191dc950\"\n}"}
- {Field: tenant_id, Value: aefde53ff77d4c8bba639b26ccff55fc}
```

## public keyは事前に登録しておいてください
わたしは、ssh public keyは際にConoHaのwebコンパネでさきに登録しています。

ここでは、”my-local-key” を使いますので確認

```bash:shell
$ openstack keypair list -f csv 2>/dev/null
"Name","Fingerprint"
"apps-key-2015-06-17-21-00","74:a3:4f:79:92:da:5d:58:a5:0b:50:3f:5f:ed:d5:b8"
"my-local-key","6c:49:66:fa:67:7c:20:e6:b5:e9:75:5a:40:51:b2:5b"
```

## サーバ作成
openstackコマンドだと、サーバ作成はこうなります。

```bash:shell
$ openstack server create --image vmi-ubuntu-14.04-amd64 --flavor g-1gb \
  --key-name my-local-key --security-group ssh-works \
  --property "instance_name_tag=s3ql_repos" new-server -f value
```

実行はこんな感じ

```bash:shell
$ openstack server create --image vmi-ubuntu-14.04-amd64 --flavor g-1gb \
  --key-name my-local-key --security-group ssh-works \
  --property "instance_name_tag=s3ql_repos" new-server -f value

MANUAL
nova

cn-a13008.g2.sjc1.v4
sjc1-00004ec4
0
None
building
None
None



Fg@qYejp5
True
2015-12-12T14:12:44Z
g-1gb (7eea7469-0d85-4f82-8050-6ae742394681)

510d823c-8098-4bba-bdf0-caf4d099d2cc
vmi-ubuntu-14.04-amd64 (a87dfe9f-a8a4-4634-9a40-dbeba7ee7013)
my-local-key
163-44-113-90
[]
0
aefde53ff77d4c8bba639b26ccff55fc
```

もちろん、ConoHaのコンパネから作成してもOKです。


## ssh loginしてs3qlのセットアップ

Ubuntu公式からは python 2.7で動く古いs3ql v1.16しか入っていません。
http://www.ubuntuupdates.org/package/core/trusty/universe/proposed/s3ql

s3qlの最新版はpython3のスレッドモデルに最適化されているので、PPAで別物を呼び出します。
その前に、ssh loginして、apt情報更新

```bash:shell
$ ssh root@v163-44-112-214.a009.g.sjc1.static.cnode.io

root@163-44-112-214:~# aptitude update
```

もし、s3ql 1.16とか入っていたら、使ってないなら削除しちゃいます

```bash:shell
n-gohko@helium-conoha:~$ dpkg -l s3ql
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                           Version                      Architecture                 Description
+++-==============================================-============================-============================-=================================================================================================
ii  s3ql                                           1.16-1                       amd64                        Full-featured file system for online data storage

n-gohko@helium-conoha:~$ sudo aptitude remove s3ql
The following packages will be REMOVED:
  libcrypto++9{u} libjs-jquery{u} libjs-sphinxdoc{u} libjs-underscore{u} python-apsw{u} python-llfuse{u} python-lzma{u} python-pycryptopp{u} python-support{u} s3ql
```

## PPA登録(ppa:nikratio/s3ql)
個別メンテナーで作っている人がいるので、PPAで利用します
https://launchpad.net/~nikratio/+archive/ubuntu/s3ql

いかのコマンドでPPAを追加します
sudo add-apt-repository ppa:nikratio/s3ql 


実際はこんな感じ

```bash:shell
n-gohko@helium-conoha:~$ sudo add-apt-repository ppa:nikratio/s3ql
 Ubuntu packages of S3QL (http://code.google.com/p/s3ql/). The PPA also contains backported versions of all dependencies for which the version in the Ubuntu archive is too old for use with S3QL.
 More info: https://launchpad.net/~nikratio/+archive/ubuntu/s3ql
Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmpbjizpp9z/secring.gpg' created
gpg: keyring `/tmp/tmpbjizpp9z/pubring.gpg' created
gpg: requesting key 9958C967 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmpbjizpp9z/trustdb.gpg: trustdb created
gpg: key 9958C967: public key "Launchpad S3QL" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK
root@163-44-112-214:~#
```

## conoha swift object storage s3ql
s3qlをOpenStack Swiftで使う話は検索すると意外に出てこない
https://dev.cloudwatt.com/en/blog/s3ql-on-cloudwatt-openstack-plateform.html
>> 参照URL (1)

http://www.rath.org/s3ql-docs/manual.pdf
>> 参照URL (2)
なので、とりあえず、インストールしてからソースを見ながら試行錯誤することになる
(swift s3ql Softlayer, swift s3ql Rackspaceなどのキーワードで検索すると、ひょっとしたら出てくるかもしれない)

https://launchpad.net/~nikratio/+archive/ubuntu/s3ql
(Adding this PPA to your system を見て、14.04LTSの場合、Trusty (14.04)をプルダウンから選択)

以下のコマンドを実行

```bash:shell
sudo add-apt-repository ppa:nikratio/s3ql
```

PPAを追加後、インストール

```bash:shell
sudo aptitude update && aptitude install s3ql
```


### python3でインストールされる

```bash:shell
n-gohko@helium-conoha:~$ sudo aptitude install s3ql
The following NEW packages will be installed:
  libgmp10{a} libjs-jquery{a} libjs-sphinxdoc{a} libjs-underscore{a} python3-apsw{a} python3-chardet{a} python3-crypto{a} python3-defusedxml{a} python3-dugong{a} python3-llfuse{a} python3-pkg-resources{a}
  python3-requests{a} python3-six{a} python3-urllib3{a} s3ql
0 packages upgraded, 15 newly installed, 0 to remove and 27 not upgraded.
Need to get 1445 kB/1611 kB of archives. After unpacking 6698 kB will be used.
Do you want to continue? [Y/n/?] y
```


確認、2.15が入っていれば大丈夫

```bash:shell
n-gohko@helium-conoha:~$ dpkg -l | grep s3ql
ii  s3ql                                                  2.15+dfsg-1~36~ubuntu14.04.1                        amd64        Full-featured file system for online data storage
n-gohko@helium-conoha:~$ mkfs.s3ql --version
S3QL 2.15
```

## openstack client 入れる
```bash:shell
sudo apt-get install ubuntu-cloud-keyring
```

## juno指定のpkgの場合、いれる、入れない場合には、ubuntuのリポジトリ内部からopenstack clientを入れることになる

とりあえず、junoのcloud archiveを使います。

```bash:shell
echo "deb http://ubuntu-cloud.archive.canonical.com/ubuntu trusty-updates/juno main" > /etc/apt/sources.list.d/cloudarchive-juno.list
```

## swiftのclientは個別に入れる
あとで、swiftコンテナの作成と内容の確認に使います

```bash:shell
n-gohko@helium-conoha:~$ sudo aptitude search swiftclient
i   python-swiftclient                                                                                            - Client library for Openstack Swift API.
```

## OSC(OpenStack client)をいれる
さきほどjunoのaptリポジトリを設定したので、junoで入ります。
clientなので、最新を入れてもいいんですけどね。

```bash:shell
n-gohko@helium-conoha:~$ sudo aptitude install python-openstackclient
以下の新規パッケージがインストールされます:
  python-cinderclient{a} python-cliff{a} python-cliff-doc{a} python-cmd2{a} python-glanceclient{a} python-json-patch{a} python-json-pointer{a} python-jsonpatch{a} python-jsonschema{a} python-keyring{a} python-mock{a}
  python-novaclient{a} python-openstackclient python-pyparsing{a} python-secretstorage{a} python-warlock{a}
0 個のパッケージを更新、 16 個を新たにインストール、 0 個を削除予定、1 個が更新されていない。
578 k バイトのアーカイブを取得する必要があります。 展開後に 4,707 k バイトのディスク領域が新たに消費されます。
先に進みますか? [Y/n/?] y
取得: 1 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-pyparsing all 2.0.1+dfsg1-1build1 [34.3 kB]
取得: 2 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-cmd2 all 0.6.7-2fakesync1build1 [22.2 kB]
取得: 3 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-json-pointer all 1.0-2build1 [5,158 B]
取得: 4 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-jsonpatch all 1.3-4 [9,088 B]
取得: 5 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-json-patch all 1.3-4 [2,312 B]
取得: 6 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-mock all 1.0.1-3 [23.8 kB]
取得: 7 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-jsonschema all 2.3.0-1build1 [27.2 kB]
取得: 8 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-warlock all 1.1.0-0ubuntu2 [5,278 B]
取得: 9 http://jp.archive.ubuntu.com/ubuntu/ trusty-updates/main python-cinderclient all 1:1.0.8-0ubuntu2 [72.4 kB]
取得: 10 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-cliff all 1.4.5-1ubuntu2 [16.7 kB]
取得: 11 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-keyring all 3.5-1 [51.8 kB]
取得: 12 http://jp.archive.ubuntu.com/ubuntu/ trusty-updates/main python-novaclient all 1:2.17.0-0ubuntu1.2 [140 kB]
取得: 13 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-glanceclient all 1:0.12.0-0ubuntu1 [34.1 kB]
取得: 14 http://jp.archive.ubuntu.com/ubuntu/ trusty/universe python-openstackclient all 0.3.0-1ubuntu1 [81.1 kB]
取得: 15 http://jp.archive.ubuntu.com/ubuntu/ trusty-updates/main python-secretstorage all 2.0.0-1ubuntu1.1 [11.7 kB]
取得: 16 http://jp.archive.ubuntu.com/ubuntu/ trusty/main python-cliff-doc all 1.4.5-1ubuntu2 [40.8 kB]
578 kB を 0秒 秒で取得しました (831 kB/s)
以前に未選択のパッケージ python-pyparsing を選択しています。
(データベースを読み込んでいます ... 現在 321845 個のファイルとディレクトリがインストールされています。)
.../python-pyparsing_2.0.1+dfsg1-1build1_all.deb を展開する準備をしています ...
python-pyparsing (2.0.1+dfsg1-1build1) を展開しています...
以前に未選択のパッケージ python-cmd2 を選択しています。
.../python-cmd2_0.6.7-2fakesync1build1_all.deb を展開する準備をしています ...
<<<<<<<<<<<< snip >>>>>>>>>>>>
man-db (2.6.7.1-1ubuntu1) のトリガを処理しています ...
doc-base (0.10.5) のトリガを処理しています ...
doc-base ファイルを 1 個追加 を処理中...
python-pyparsing (2.0.1+dfsg1-1build1) を設定しています ...
python-cmd2 (0.6.7-2fakesync1build1) を設定しています ...
python-json-pointer (1.0-2build1) を設定しています ...
python-jsonpatch (1.3-4) を設定しています ...
update-alternatives: /usr/bin/jsondiff (jsondiff) を提供するために 自動モード で /usr/bin/python2-jsondiff を使います
update-alternatives: /usr/bin/jsonpatch (jsonpatch) を提供するために 自動モード で /usr/bin/python2-jsonpatch を使います
python-json-patch (1.3-4) を設定しています ...
python-mock (1.0.1-3) を設定しています ...
python-jsonschema (2.3.0-1build1) を設定しています ...
python-warlock (1.1.0-0ubuntu2) を設定しています ...
python-cinderclient (1:1.0.8-0ubuntu2) を設定しています ...
python-cliff (1.4.5-1ubuntu2) を設定しています ...
python-keyring (3.5-1) を設定しています ...
python-novaclient (1:2.17.0-0ubuntu1.2) を設定しています ...
python-glanceclient (1:0.12.0-0ubuntu1) を設定しています ...
python-openstackclient (0.3.0-1ubuntu1) を設定しています ...
python-secretstorage (2.0.0-1ubuntu1.1) を設定しています ...
python-cliff-doc (1.4.5-1ubuntu2) を設定しています ...

n-gohko@helium-conoha:~$
```

これで、インストールはここまで


# s3ql 設定とHack (plugin作成)

ここから設定と、設定のためのカスタマイズ(必要悪)

## swiftにアクセスして入れ物のコンテナを作る
tokyoリージョンでswiftコマンドで入れ物を作ります。
後で、内容物を確認します。

この辺りを参考にしてください
https://www.conoha.jp/conoben/archives/2648

```bash:shell
n-gohko@helium-conoha:~$ swift list 
expandrive
win-hp-backup

n-gohko@helium-conoha:~$ swift post s3ql_pool

n-gohko@helium-conoha:~$ swift list
expandrive
s3ql_pool
win-hp-backup
```

"s3ql_pool" という入れ物(コンテナ)を作りました



## ローカルコンフィグdir作成

fuseマウントですので、user環境でマウントされます。
rootでマウントする場合には、rootのユーザに設定します。

私は、"n-gohko"でマウントしました。rsyncでのhome directory(Dropboxを含む)のバックアップに使っているので、そのような使い方には通常使っているユーザのほうがよいですね。

configとcacheのディレクトリをマウントするユーザHomeに "~/.s3ql" を作成します。

```bash:shell
n-gohko@helium-conoha:~$ mkdir ~/.s3ql && install -b -m 600 /dev/null ~/.s3ql/authinfo2
```

s3qlでマウントする場所を作っておきます。

```bash:shell
$ mkdir -p ~/mnt/s3ql
```


## (うまくいかなかった)s3ql swiftksコンフィグ作成

本来ならば、swiftのコンフィグはswiftksというタイプのstorage-urlで設定するのですが、なんかうまく行きませんでした。

参照URL (1) にある設定では

```bash:shell
n-gohko@helium-conoha:~$ cat ~/.s3ql/authinfo2
[swift]
backend-login: <tenant_name>:<username>
backend-password: <password>
storage-url: swiftks://identity.fr1.cloudwatt.com/fr1:<container_s3ql>
```

という感じで設定されています。

ConoHa swift object storageだと、次のようになるはずなんですけど、うまく動きませんでした。

```bash:shell
n-gohko@helium-conoha:~$ cat .s3ql/authinfo2
[swift]
backend-login: gnct59999999:gncu59999999
backend-password: hogenaisho
storage-url: swiftks://identity.tyo1.conoha.io/tyo1/:s3ql_pool
```

うまくいかなかった内容について調べてみると、swiftks(keystone auth v2.0)の設定を動かしているのは、s3qlのbackendドライバで設定されています。

swiftksでパッケージのファイルを検索すると、下記のファイルが見つかります。

```bash:shell
n-gohko@helium-conoha:~$ dpkg -L s3ql | grep swiftks
/usr/lib/s3ql/s3ql/backends/swiftks.py
```

開くと、次に示す "_pase_storage_url()" のところに正規表現でstorage-urlを分解しているのですが、ここでうまくいかない感じ。

```bash:shell
n-gohko@helium-conoha:~$ cat -n /usr/lib/s3ql/s3ql/backends/swiftks.py | head -n 57 | tail -n 31
    27
    28	    @copy_ancestor_docstring
    29	    def _parse_storage_url(self, storage_url, ssl_context):
    30
    31	        hit = re.match(r'^[a-zA-Z0-9]+://' # Backend
    32	                       r'([^/:]+)' # Hostname
    33	                       r'(?::([0-9]+))?' # Port
    34	                       r'/([a-zA-Z0-9._-]+):' # Region
    35	                       r'([^/]+)' # Bucketname
    36	                       r'(?:/(.*))?$', # Prefix
    37	                       storage_url)
    38	        if not hit:
    39	            raise QuietError('Invalid storage URL', exitcode=2)
    40
    41	        hostname = hit.group(1)
    42	        if hit.group(2):
    43	            port = int(hit.group(2))
    44	        elif ssl_context:
    45	            port = 443
    46	        else:
    47	            port = 80
    48	        region = hit.group(3)
    49	        containername = hit.group(4)
    50	        prefix = hit.group(5) or ''
    51
    52	        self.hostname = hostname
    53	        self.port = port
    54	        self.container_name = containername
    55	        self.prefix = prefix
    56	        self.region = region
    57
```

```bash:shell
n-gohko@helium-conoha:~$ mkfs.s3ql --plain --authfile ~/.s3ql/authinfo2 \
  --debug swiftks://identity.tyo1.conoha.io/tyo1/:s3ql_pool
2015-12-13 04:00:12.492 15887 MainThread s3ql.backends.common.get_ssl_context: Reading default CA certificates.
2015-12-13 04:00:12.493 15887 MainThread root.excepthook: Invalid storage URL
```

という感じで、うまくいかない、うう。
rackspaceのアカウントではうまくいったので、エラーのstorage urlのところで詰まっているだろうとおもったのです。

いろいろやったのですが、Hackで切り抜けることにします。

## (Hack) conohaswiftというstorage URLをrackspaceの複製して作る

ここで、面倒になったので、conohaswiftというstorage pluginを作って使えるようにします。

backendのストレージプラグインはgrepするとbackendsという場所に入っていることがわかります。

```bash:shell
n-gohko@163-44-112-214:~$ dpkg -L s3ql | grep backends
/usr/share/doc/s3ql/html/_sources/backends.txt
/usr/share/doc/s3ql/html/backends.html
/usr/lib/s3ql/s3ql/backends
/usr/lib/s3ql/s3ql/backends/gs.py
/usr/lib/s3ql/s3ql/backends/rackspace.py
/usr/lib/s3ql/s3ql/backends/s3.py
/usr/lib/s3ql/s3ql/backends/s3c.py
/usr/lib/s3ql/s3ql/backends/swift.py
/usr/lib/s3ql/s3ql/backends/common.py
/usr/lib/s3ql/s3ql/backends/local.py
/usr/lib/s3ql/s3ql/backends/pool.py
/usr/lib/s3ql/s3ql/backends/__init__.py
/usr/lib/s3ql/s3ql/backends/swiftks.py
/usr/lib/s3ql/s3ql/backends/comprenc.py
```

rackspace classは、swiftks  classをそのまま呼んでいて、"_pase_storage_url()" のところでswiftksの認証を上書きしています。
なので、これに習って、conohaswift.py というドライバファイルを rackspace.py の複製として作って、storage URLのパースをスキップします。

```bash:shell
n-gohko@163-44-112-214:~$ pushd /usr/lib/s3ql/s3ql/backends/
/usr/lib/s3ql/s3ql/backends ~

n-gohko@163-44-112-214:/usr/lib/s3ql/s3ql/backends$ sudo cp -avf rackspace.py conohaswift.py
sudo: unable to resolve host 163-44-112-214
[sudo] password for n-gohko:
'rackspace.py' -> 'conohaswift.py'
```

バツクエンドの中身

```bash:shell
n-gohko@163-44-112-214:/usr/lib/s3ql/s3ql/backends$ ls -l
total 180
-rw-r--r-- 1 root root   634 Sep 18 08:42 __init__.py
drwxr-xr-x 2 root root  4096 Dec 12 06:44 __pycache__
-rw-r--r-- 1 root root 22827 Sep 18 08:42 common.py
-rw-r--r-- 1 root root 33419 Sep 28 20:09 comprenc.py
-rw-r--r-- 1 root root  1232 Sep 18 08:42 conohaswift.py
-rw-r--r-- 1 root root  9859 Sep 18 08:42 gs.py
-rw-r--r-- 1 root root 10241 Sep 28 20:09 local.py
-rw-r--r-- 1 root root  1872 Sep 18 08:42 pool.py
-rw-r--r-- 1 root root  1232 Sep 18 08:42 rackspace.py
-rw-r--r-- 1 root root  6270 Sep 18 08:42 s3.py
-rw-r--r-- 1 root root 37709 Sep 28 20:09 s3c.py
-rw-r--r-- 1 root root 19233 Sep 18 08:42 swift.py
-rw-r--r-- 1 root root  4736 Sep 18 08:42 swiftks.py

```

conohaswift.pyの中身は次のようになります。

```python:/usr/lib/s3ql/s3ql/backends/conohaswift.py
'''
conohaswift.py - this file is part of S3QL.

Copyright © 215 n-gohko

This work can be distributed under the terms of the GNU GPLv3.
'''

from ..logging import logging, QuietError # Ensure use of custom logger class
from . import swiftks
from ..inherit_docstrings import copy_ancestor_docstring
import re

log = logging.getLogger(__name__)

class Backend(swiftks.Backend):
    """A backend to store data in ConoHa swift Object Storage"""

    @copy_ancestor_docstring
    def _parse_storage_url(self, storage_url, ssl_context):

        hit = re.match(r'^conohaswift://' # Backend
                       r'([^/:]+)' # Region
                       r'/([^/]+)' # Bucketname
                       r'(?:/(.*))?$', # Prefix
                       storage_url)
        if not hit:
            raise QuietError('Invalid storage URL', exitcode=2)

        region = hit.group(1)
        containername = hit.group(2)
        prefix = hit.group(3) or ''

        if ssl_context:
            port = 443
        else:
            port = 80
        port = 443

        self.hostname = 'identity.tyo1.conoha.io'
        self.port = port
        self.container_name = containername
        self.prefix = prefix
        self.region = region

```
backends のロードの設定に追加するために、”\_\_init\_\_.py” ファイルを修正します。

```python:/usr/lib/s3ql/s3ql/backends/__init__.py
'''
backends/__init__.py - this file is part of S3QL.

Copyright © 2008 Nikolaus Rath <Nikolaus@rath.org>

This work can be distributed under the terms of the GNU GPLv3.
'''

from . import local, s3, gs, s3c, swift, rackspace, swiftks, conohaswift

#: Mapping from storage URL prefixes to backend classes
prefix_map = { 's3': s3.Backend,
               'local': local.Backend,
               'gs': gs.Backend,
               's3c': s3c.Backend,
               'swift': swift.Backend,
               'conohaswift': conohaswift.Backend,
               'swiftks': swiftks.Backend,
               'rackspace': rackspace.Backend }

__all__ = [ 'common', 'pool', 'comprenc' ] + list(prefix_map.keys())

```

## (Hack:2) conohaswiftというstorage URLで接続する

書き換えたので、マウントするユーザのディレクトリに戻って、設定ファイルを書き換えます。

```bash:shell
n-gohko@163-44-112-214:~$ cat .s3ql/authinfo2
[swift]
backend-login: gnct59999999:gncu59999999
backend-password: hogenaisho
storage-url: conohaswift://tyo1/s3ql_pool
```


mkfs.s3qlを実行します。”--debug”オプションは動作確認のためなので、
mkfs.s3ql --plain --authfile ~/.s3ql/authinfo2 conohaswift://tyo1/s3ql_poo
みたいな感じで良いです。


```bash:shell
n-gohko@163-44-112-214:~$ mkfs.s3ql --plain --authfile ~/.s3ql/authinfo2 --debug conohaswift://tyo1/s3ql_pool
2015-12-13 04:43:17.027 15989 MainThread s3ql.backends.common.get_ssl_context: Reading default CA certificates.
2015-12-13 04:43:17.027 15989 MainThread s3ql.backends.swift._do_request: started with 'GET', '/', None, {'limit': 1}, None, None
2015-12-13 04:43:17.027 15989 MainThread s3ql.backends.swift._do_request: no active connection, calling _get_conn()
2015-12-13 04:43:17.027 15989 MainThread s3ql.backends.swiftks._get_conn: started
<< snip >>
2015-12-13 04:43:21.904 15989 MainThread s3ql.backends.swift.open_write: started with s3ql_seq_no_1
2015-12-13 04:43:21.904 15989 MainThread s3ql.backends.s3c.close: started with s3ql_seq_no_1
2015-12-13 04:43:21.904 15989 MainThread s3ql.backends.swift._do_request: started with 'PUT', '/s3ql_seq_no_1', None, None, CaseInsensitiveDict({'Content-Type': 'application/octet-stream', 'X-Object-meta-002': "'encryption': 'None',", 'X-Object-meta-format': 'raw2', 'X-Object-meta-001': "'compression': 'LZMA',", 'X-Object-meta-003': "'format_version': 2,", 'X-Object-meta-000': "'data': b'eyAgfQ==',", 'X-Object-meta-md5': '1UH6aTHbuVf1fhc0/H8WUA=='}), <_io.FileIO name=6 mode='rb+'>
2015-12-13 04:43:21.905 15989 MainThread s3ql.backends.swift._do_request_inner: started with PUT /v1/nc_aefde53ff77d4c8bba639b26ccff55fc/s3ql_pool/s3ql_seq_no_1
2015-12-13 04:43:21.905 15989 MainThread s3ql.backends.swift._do_request_inner: waiting for 100-continue
2015-12-13 04:43:22.030 15989 MainThread s3ql.backends.swift._do_request_inner: writing body data
n-gohko@163-44-112-214:~$
```

Hackで作ったあらたなstorage urlでマウントします。
mount.s3ql  conohaswift://tyo1/s3ql_pool ~/mnt/s3ql

```bash:shell
n-gohko@163-44-112-214:~$ mount.s3ql  conohaswift://tyo1/s3ql_pool ~/mnt/s3ql
Using 4 upload threads.
Autodetected 4052 file descriptors available for cache entries
Using cached metadata.
Setting cache size to 33058 MB
Mounting filesystem...
```

マウントされていることを確認
```bash:shell

n-gohko@163-44-112-214:~$ df
Filesystem                    1K-blocks    Used  Available Use% Mounted on
/dev/vda1                      50442940 5542204   42315344  12% /
none                                  4       0          4   0% /sys/fs/cgroup
udev                             497964      12     497952   1% /dev
tmpfs                            101748     388     101360   1% /run
none                               5120       0       5120   0% /run/lock
none                             508736       0     508736   0% /run/shm
none                             102400       0     102400   0% /run/user
conohaswift://tyo1/s3ql_pool 1073741824       0 1073741824   0% /home/n-gohko/mnt/s3ql
```

## なにもコピーしていない状態
mkfs.s3qlでFormatして、マウントした状態で、swiftコンテナ”s3ql_pool”の中身を確認します。

```bash:shell
[n-gohko@163-44-112-214]$ swift list --lh s3ql_pool 2>/dev/null
 120 2015-12-13 12:43:21 s3ql_metadata
 120 2015-12-13 12:43:19 s3ql_metadata_new
  64 2015-12-13 12:43:21 s3ql_seq_no_1
  64 2015-12-13 12:46:15 s3ql_seq_no_2
 368
```

初期状態では、メタデータファイルだけあります。
mkfs.s3qlを”--plain”オプションを指定したことで、暗号化は無しです。


## 自分develディレクトリをrsyncする
では、rsyncで書き込んでみましょう。
手元の “~/devel” ディレクトリが 3.7GBぐいらあるので、書き込んでみます。
```bash:shell
n-gohko@163-44-112-214:~$ du -hs devel
3.7G    devel
```

rsync中にマウントされたディレクトリは次のように見えます。

```bash:shell
[n-gohko@163-44-112-214]$ ls -l ~/mnt/s3ql/
total 0
drwxrwxr-x 1 n-gohko n-gohko 0 Sep 28 20:31 devel
drwx------ 1 n-gohko n-gohko 0 Dec 13 04:43 lost+found
```

アカウント設定を先ほどおいた “~/.s3ql” ディレクトリの中身を見ると、次のようになります。

```bash:shell
[n-gohko@163-44-112-214]$ du -hs ~/.s3ql/*
4.0K    /home/n-gohko/.s3ql/authinfo2
68M     /home/n-gohko/.s3ql/conohaswift:=2F=2Ftyo1=2Fs3ql_pool-cache
1.8M    /home/n-gohko/.s3ql/conohaswift:=2F=2Ftyo1=2Fs3ql_pool.db
4.0K    /home/n-gohko/.s3ql/conohaswift:=2F=2Ftyo1=2Fs3ql_pool.params
4.0K    /home/n-gohko/.s3ql/mount.log
0       /home/n-gohko/.s3ql/mount.s3ql_crit.log
```
cacheディレクトリは転送のcache、.dbファイルはsqliteファイルです。
実は、この仕組で、ファイルを管理しているのが、このdbなので、このdbをマルチノードで共有アクセスできるようにすれば、複数のノードでアクセスするようにできるのかなと思いました。

```bash:shell
[n-gohko@163-44-112-214]$ file ~/.s3ql/conohaswift:=2F=2Ftyo1=2Fs3ql_pool.db
/home/n-gohko/.s3ql/conohaswift:=2F=2Ftyo1=2Fs3ql_pool.db: SQLite 3.x database
```

パラメータファイル .params はテキストにjsonで書いてあるみたいですね
```bash:shell
[n-gohko@163-44-112-214]$ file ~/.s3ql/conohaswift:=2F=2Ftyo1=2Fs3ql_pool.params
/home/n-gohko/.s3ql/conohaswift:=2F=2Ftyo1=2Fs3ql_pool.params: ASCII text, with no line terminators
```

rsyncの途中で du とかも取れます。
```bash:shell
n-gohko@163-44-112-214:~$ du -hs ~/mnt/s3ql/devel
1.7G    /home/n-gohko/mnt/s3ql/devel
```



メタデータとオブジェクトデータに別れてデータが転送される。
データオブジェクト単体では、そのままでは、どれがどれかはわからないですね。
メタデータファイルもあります。

```bash:shell
[n-gohko@163-44-112-214]$ swift list --lh s3ql_pool  2>/dev/null | grep -v '_data_'
 120 2015-12-13 12:43:21 s3ql_metadata
 120 2015-12-13 12:43:19 s3ql_metadata_new
  64 2015-12-13 12:43:21 s3ql_seq_no_1
  64 2015-12-13 12:46:15 s3ql_seq_no_2
1.1G
```
_data_ファイルはたくさんなので、ちょっとだけ

```bash:shell
[n-gohko@163-44-112-214] $ swift list --lh s3ql_pool  2>/dev/null | grep  '_data_' | head -n 3
 116 2015-12-13 12:55:30 s3ql_data_1
746K 2015-12-13 12:55:35 s3ql_data_10
 79K 2015-12-13 12:56:36 s3ql_data_100
```

s3qlのumountは、次のようにumount.s3ql を使います。
```bash:shell
[n-gohko@163-44-112-214]$ umount.s3ql ~/mnt/s3ql
[n-gohko@163-44-112-214]$ ls -l ~/mnt/s3ql/
total 0
```

次にマウントされた時に、cacheサイズは更新されます。
```bash:shell
n-gohko@163-44-112-214:~$ mount.s3ql  conohaswift://tyo1/s3ql_pool ~/mnt/s3ql
Using 4 upload threads.
Autodetected 4052 file descriptors available for cache entries
Using cached metadata.
Setting cache size to 33052 MB
Mounting filesystem...
n-gohko@163-44-112-214:~$
```


いろいろdevelに入れていたので、日本語ファイル含めて転送。
とくに日本語のファイル名もそのまま。

結局、~/.s3ql/  ディレクトリにキャッシュされるので、ローカルディスクの速度が書き込み速度となる。


# 最後に
とりあえず、mountして、rsyncするところまでですが、組み合わせのインテグレーションや改修の内容はちょっと膨らみます。s3qlの開発の本家がどういう方向性でやっているのかも気になります。