ワンボタンでキミのConoHaにGentooが！

この記事は、[ConoHa Advent Calendar2017](https://qiita.com/advent-calendar/2017/conoha)の19日目の記事です。

18日担当の@Prog24さんに続いて、19日担当の@nothinkです。以下なんか口調がおかしいですが気にしないでください。
~~完成品だけ見たい人は何も考えずに下へ。~~
~~https://conohoo.nothink.info/~~
**[2018/01/23]** アドベントカレンダーの年を跨いだのでデモは終了させていただきました。

# 序文

なぜ[ConoHa](https://www.conoha.jp/conoha/)には[Gentoo](https://www.gentoo.org/)のテンプレートが無いのか。
無いならば作ればいい？いや、それは我々の回答ではない。
我々が望むのは、無慈悲なまでに破壊的なGentooという選択[^1]である。

[^1]: 「Gentooとは選択です」["Gentoo is all about choices"](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/About#Welcome)

あ、OpenStackの勉強も兼ねるよ？


# [Installing Gentoo](https://wiki.gentoo.org/wiki/Handbook:AMD64#Installing_Gentoo)を自動化すると？

普通ConoHaにGentooをインストールする場合、イメージを[conoha-iso](https://github.com/hironobu-s/conoha-iso)でマウントして[Gentoo Handbook](https://wiki.gentoo.org/wiki/Handbook)の[Installing Gentoo](https://wiki.gentoo.org/wiki/Handbook:AMD64#Installing_Gentoo)を順に行う。

## スクリプト化

この処理を2枚のシェルスクリプトにまとめてみよう。
何故２枚かというと、Gentooはインストール中にchrootするのでその内外でスクリプトを分割する必要があるためだ。

https://github.com/nothink/conohoo/tree/master/src/sh/manual

雑多になるので詳細は別の記事にて。

https://qiita.com/nothink/items/3be5b632d3174645f707

手順としてはconoha-isoを用いて Minimal Installation CD を挿入して起動し、この２つのbashスクリプトを直下に配置して待てばGentooになる。

このようにインストールの省力化は結構簡単なのだが、

1.　conoha-isoを導入
2.　conoha-isoでイメージを導入して再起動
3.　コンソールを開き、必要ならばsshdを起動
4.　２枚のスクリプトをコピペなり落とすなりで配置

という手順があるので気軽に布教するには今一歩。

## スタートアップスクリプト

スタートアップスクリプトを使えば作業を自動化できそうだが、これが意外と難しい。

今回のように「新しいOSに書き換えるスタートアップスクリプトを書きたい！」となった時に、ConoHaでは次の問題が発生する。


- スタートアップスクリプトは既存のフレーバー、イメージからの新規作成のみ
- ISOから起動しているOSの時点では既に「スタートアップ」ではない
- ルート(ConoHaのGlancenにある殆どのイメージがGPT単一ボリュームなので、/dev/vda2)をアンマウントする方法がない
- ルート以外のパーティションは /dev/vda に無い[^2]
- ディスクを追加して別ボリュームとして扱っても、そこから起動することが厳しい[^3]
- コントロールパネル外で構築したイメージを(Glanceに)追加するAPIは非公開

[^2]: 正確にはGPTが使うBIOSブートパーティション(/dev/vda1)はあるが…
[^3]: 詳細は確認していないが、VPS起動してスタートアップスクリプトが走るタイミングでは/dev/vdbが存在しない可能性あり


スタートアップスクリプト自体はOpenStackの `servers` の `user_data` を指定することで行われる。これはGlanceからのインスタンス追加リクエストであり、インストールボリュームからの起動前提の一般的なGentooインストールは厳しい。

また、OpenStack APIを実際に叩いてみるとConoHaではオミットされている部分があることがわかる。
これには、外部qcow2イメージからの新規作成なども含まれる。

https://qiita.com/nothink/items/db34dcb5db7f1b3c1789

なので、今回のようなOSインストール処理をスタートアップスクリプト単体で行うのは難しい。

## Stage3への置き換え

スタートアップスクリプトで唯一可能そうな手段は、既存の他ディストリビューションをGentooに置き換えるという方法である。

https://wiki.gentoo.org/wiki/Replace_a_Linux_installation_with_Gentoo_in-place

要は、Stage3を他のディストリビューション上に上書きしてGentoo化する。
非推奨なインストール方法だが、原理が単純なGentooでは意外と何とかなってしまう。

ちなみにどうやるかというと、

1. Stage3 tarballを落とす
2. 重要なファイル (/etc/fstab, /sbin/modprobe 等) を退避
3. 書き換え対象のすべてのファイルのタイムスタンプをUNIX Epochなどの日付に変更
4. root権限でStage3 tarballを展開して上書き
5. 既存kernelで再起動
6. 日付で書き換え対象ファイルを判定し、既存ファイルをroot権限で全て削除

となる。

ただ、上記例でもkernelは流用している通り、オンメモリのkernelを一発で置き換えるのはあまり得策ではなさそうだし、流れも煩雑になる。
だが、やはりkernelはGentoo上でビルドしたい。
よって、ここでは一度再起動して改めてkernelを構築する方法を取る。

再起動後の自動処理は [local](https://wiki.gentoo.org/wiki//etc/local.d) を使うのが簡単なのでこれを使う。
自動処理は処理完了後、自身を削除して再起動、もしくはシャットダウンして終了となる。

# API経由で追加する

せっかくなのでどこぞのサイトからワンボタンでGentooを追加したい。
OpenStack APIをどこかから叩いてインストールする手段を検証してみた。

## ブラウザ上からでは？

はじめはfetch APIで叩こうと思ったものの、ConoHaのOpenStack REST APIはCORSヘッダを返さない仕様[^4]のようなので全てをブラウザ上で行うのは厳しい。

https://qiita.com/OttyLab/items/067eafb62c90977cc09c

## 仕方ないのでサーバ上で

ブラウザ上から叩くことが出来ない以上、何らかのサーバサイドを用いるしか方法はない。
今回は時間がないのでTornadoで実装してみた。

これの何が不満かというと、OpenStack APIのAPIパスワードは平文で送られるからだ。
経路がTLSとはいえ、サーバサイドから叩くからには一度メモリ上に平文でAPIパスワードを確保しなければならない。これは他の人に操作してもらうにはあまり喜ばしくない。
今回はチュートリアル的なものということで、そのへんは勘弁していただきたい。

# 成果物

~~ということで次のようなサイトが出来た。~~

~~https://conohoo.nothink.info/~~
**[2018/01/23]** アドベントカレンダーの年を跨いだのでデモは終了させていただきました。

ソースコードは [GitHub上に配置](https://github.com/nothink/conohoo) してあるので参照を。

<img width="467" alt="名称未設定.png" src="https://qiita-image-store.s3.amazonaws.com/0/79463/7df69f56-5c07-1e5f-a44d-3bfa9d1ff855.png">

一応APIパスワードがサーバに渡ってしまうことだけは留意してもらいたい。
特に変な処理はしていないが他人のマシンのメモリ上にAPIパスワードが平文で存在してしまうのは確かなため、コントロールパネルで一時的にAPIパスワードを変更するなどしたほうが良いかもしれない。

- リージョン
- テナントID
- APIユーザー名
- APIパスワード

を入れてボタンをクリックするとトークン取得開始。

<img width="417" alt="名称未設定２.png" src="https://qiita-image-store.s3.amazonaws.com/0/79463/f29571d5-fb25-5dde-4ba9-cddf571c171a.png">

トークンが正常に取得できたらインストールに必要な項目を選択する。

- VMプラン
- VPSにつけるネームタグ
- 初期rootパスワード

の３項目を指定、VM追加しても良いならここでボタンをクリックしてしばし待つ。

急造でエラー処理が抜けていて申し訳ないが、**ConoHaはVMのパスワードに制限がある**ことを注意してもらいたい。

https://www.conoha.jp/docs/compute-create_vm.html

具体的には、以下のものをrootパスワードに指定していないとAPIがエラーを返す。

>文字種：半角英大文字と、半角英小文字と、半角数字または記号の組み合わせ以外はエラー。文字数：9文字以上～70文字以内
>使用可能の記号 ⇒ ! # $ % & ? ” ' = + - _ { } [ ] ^ ~ : ; ( ) . , / | \ * @

ボタンを押してしばらくするとDebianのインスタンスが完成し、これと同時にスタートアップスクリプトが連続で走る。

<img width="492" alt="名称未設定３.png" src="https://qiita-image-store.s3.amazonaws.com/0/79463/ff93e017-d211-ce82-4fcd-a1ff60740e1a.png">

これがうまくいくと進捗画面に移るので、grubのインストールまで終わったらインストール完了。
インストール完了後にインスタンスをシャットダウンするようになっているので、そうなったら起動してもらいたい。君のConoHaコントロールパネルにGentooのVMが追加されているはずだ。

#　注意事項

ConoHaにかぎらず、VMなどをAPIから追加したらその段階で**課金が始まる**ので注意(1GのVMで1.3円/1h)。

<img width="818" alt="名称未設定.png" src="https://qiita-image-store.s3.amazonaws.com/0/79463/f34c2755-fbed-46b4-b177-9688911b7960.png">
遊び終わったら即刻削除するなり再利用するなりしよう。

……でも、Gentoo使って欲しいな。


[^4]: ひょっとしてopenrestyかなにかでイチから書いてる？　…まさかね