OSvのビルド環境の構築

OSvはMacWindows上のVirtualBoxVMwareVMware ESXiなど様々な環境で動作するのですが、ビルド環境はFedoraの最新版という極めて限られた環境でのみテストされています(理屈の上では他のディストリビューションでもビルド可能ですが、細かなパッケージの差異などのためにエラーを起こすことがあります)。

より多くの環境でビルド出来るようにビルドスクリプトを手直しするのが本筋なのですが、ここでは取り敢えずFedora環境を用意して開発を始めることを目的とします。

VMware上での開発

WindowsMacではこの方法を選択する必要があります。
Linux環境でもこの方法が使用出来ますが、後述のchroot環境を使った方が高いパフォーマンスが得られます。

VMwareをインストールしてFedoraのディスクイメージを起動します。
(ネステッドVMを使用するため、VMwareでなくてはなりません。VirtualBoxなどでは動作しません。)
VMイメージはここで配布しています。

ユーザ名とパスワードはroot:osvdev, osvdev:osvdevです。

osvdevユーザでログインを行いTerminalを立ち上げ、以下のコマンドを実行することにより開発作業を始められます。

cd osv
git pull
make -j4
./scripts/run.py -n

chroot環境での開発

Fedora以外のLinuxでの開発にはこの方法がおすすめです。
chrootディレクトリにFedoraをインストールします。
GitHub - syuu1228/fedora-chroot-image: Fedora chroot image distribution and build scriptにてchrootイメージを配布しているのでこちらを使用します。

wget -O fedora-chroot.tar.xz "https://github.com/syuu1228/fedora-chroot-image/blob/master/fedora-chroot.tar.xz?raw=true"
sudo tar -xpf fedora-chroot.tar.xz
sudo ./run-fedora.sh

chrootディレクトリ内でrootユーザのシェルが実行されます。

cd ~
./bootstrap.sh

最小限必要なパッケージをインストールします。

yum install git
git clone https://github.com/cloudius-systems/osv.git
cd osv
./scripts/setup.py
git submodule update --recursive --init
make -j4
./scripts/run.py -n

OSvのソースコードをダウンロードしてビルドを行います。

1コマンドでJavaアプリをOSvへデプロイ

OSvは、ハイパーバイザやIaaSプラットフォームへアプリケーションをデプロイすることに特化した軽量OSです(※詳しくはこちら)。
また、CapstanはGo言語で実装されたOSvのデプロイツールです(※詳しくはこちら)。

OSvはJVM上で動くアプリケーションをメインターゲットとして開発が進められており、様々なJavaアプリケーションが動作します。
この記事ではCapstanの開発版を使って1コマンドで任意のJavaアプリからOSvのディスクイメージを生成&実行してみます。

Goをインストー

sudo yum install go
export GOPATH=~/go

コマンドラインFedoraの例です。ディストリごとにパッケージマネージャのコマンドは異なります。

Capstan開発版をインストー

go get github.com/cloudius-systems/capstan
go install github.com/cloudius-systems/capstan

これで~/go/bin/にCapstanがインストールされました。
PATH指定を省略してCapstanを呼びたい場合は~/go/binにPATHを通して下さい。
その際、既にバイナリ配布版のCapstanをインストールしている場合はPATHが異なることに注意して下さい(バイナリ配布版は~/bin)。

Rhinoを試す

まずは単一のjarで配布されているRhino Javascriptインタプリタを試します。

wget ftp://ftp.mozilla.org/pub/mozilla.org/js/rhino1_7R2.zip
unzip -x rhino1_7R2.zip
~/go/bin/capstan run rhino1_7R2/js.jar

capstan run によってOSv+JVMディスクイメージにjarファイルがコピーされ、KVM上で実行されます。
実行が開始されると、OSvの起動メッセージの後にRhinoが起動してくるのでJavaScriptで遊んでみます。

Downloading cloudius/osv-openjdk/index.yaml...
160 B / 160 B [=====================================================] 100.00 % 0
Downloading cloudius/osv-openjdk/osv-openjdk.qemu.gz...
74.34 MB / 74.34 MB [===========================================] 100.00 % 3m16s
Building js...
Uploading files...
1 / 1 [=============================================================] 100.00 % 0Created instance: js
OSv v0.16
eth0: 192.168.122.15
Rhino 1.7 release 2 2009 03 22
js> print("Hello World");
Hello World
js> 1 + 2;
3
js> quit();

複数のjarファイルからなるプログラムを実行してみる

One-JARを使うと複数のjarファイルを一つにまとめることが出来るようなので、これを使ってApache FtpServerを一つのjarにまとめてOSvへデプロイしてみます。

まずFtpServerとOne-JARをダウンロードしてきて解凍します。

wget http://ftp.riken.jp/net/apache/mina/ftpserver/1.0.6/dist/ftpserver-1.0.6.zip
unzip -x ftpserver-1.0.6.zip
cd apache-ftpserver-1.0.6
wget http://jaist.dl.sourceforge.net/project/one-jar/one-jar/one-jar-0.97/one-jar-boot-0.97.jar

まとめたjarファイルを作るための一時ディレクトリを./rootに作成し、ここのjarファイルをコピーします。

mkdir -p root/main
mkdir -p root/lib
cp common/lib/*.jar root/lib
mv root/lib/ftpserver-core-1.0.6.jar root/main/
cd root
jar xvf ../one-jar-boot-0.97.jar
boot-manifest.mf

boot-manifest.mfにOne-Jar-Main-Classの行を足します。

Manifest-Version: 1.0
Main-Class: com.simontuffs.onejar.Boot
One-Jar-Main-Class: org.apache.ftpserver.main.CommandLine

capstan runを呼んでディスクイメージを生成・実行します。
FTPサーバに接続可能にするため、ネットワークをブリッジ接続にします。

jar -cvfm ../ftpserver.jar boot-manifest.mf .
cd ..
~/go/bin/capstan run -n bridge ftpserver.jar

capstan runが実行されると以下のような感じでFtpServerが起動します。

Building ftpserver...
Uploading files...
1 / 1 [=============================================================] 100.00 % 0Created instance: ftpserver
OSv v0.16
eth0: 192.168.122.77
Using default configuration
log4j:WARN No appenders could be found for logger (org.apache.ftpserver.impl.DefaultFtpServerContext).
log4j:WARN Please initialize the log4j system properly.
FtpServer started

ftpクライアントで繋いでみます。

$ ftp 192.168.122.77
Connected to 192.168.122.77 (192.168.122.77).
220 Service ready for new user.
Name (192.168.122.77:syuu): anonymous
331 Guest login okay, send your complete e-mail address as password.
Password:
530 Authentication failed.
Login failed.
ftp>

…デフォルト設定の場合に有効なユーザ名・パスワードが分からなかったのでログイン失敗しましたが、FTPサーバが上がっているようです。

OSv CLIにコマンドを追加しよう

OSv CLIの使い方 - かーねる・う゛いえむにっきで見たとおり、現状CLIのコマンドは非常に少なく、REST APIを直接呼び出して一部の操作を行わざるを得ない状態です。

そこで、コマンドを足してOSvへコントリビューションしてみるのは如何でしょうか。
例えば、dateコマンドは以下のような非常に簡単なluaスクリプトで出来ています:

local cmd = {}

cmd.desc = [[print the system date and time]]
cmd.help = [[Usage: date

Print OSv reported date.]]

cmd.main = function()
  local content, status = osv_request({"os", "date"}, "GET")
  osv_resp_assert(status, 200)
  io.write(content, '\n')
end

return cmd

osv_request()によってREST APIが呼び出され、結果がcontentに代入されてio.write()でコンソールに出力されています。
コマンドを定義するluaスクリプトはmodules/cli/commands/に コマンド名.lua という名前で配置することになっています。

まだまだapiコマンド以外からアクセス出来ないREST API上の機能がいくつもあるので、ぜひ新しいコマンドを作成してみて下さい。

OSv CLIの使い方

リモートCLIについて - かーねる・う゛いえむにっきでも紹介したCLIの使い方についてです。

リモートCLIに必要なもの

まず、Linuxホスト側でCLIをインストールする必要があります(参照)。
その上で、httpserver(REST APIサーバ)を含むOSvのイメージを実行する必要があります。

Capstan経由で配布されているディスクイメージやosv.ioで配布されているディスクイメージは全てhttpserverを含んだイメージですが、OSvをソースコードからビルドする場合はhttpserverを明示的に指定する必要があります。

つまり、

git clone https://github.com/cloudius-systems/osv.git
cd osv
git submodule update --init --recursive
make image=ruby-publify

ではなく、

git clone https://github.com/cloudius-systems/osv.git
cd osv
git submodule update --init --recursive
make image=ruby-publify,httpserver

のようにビルドする必要があります。

CLI on OSvに必要なもの

CLIとアプリケーションとで1つのコンソールを共有するので、アプリケーションと同時にCLIを実行出来るのはアプリケーションが継続的なコンソール出力を行わない・コンソール入力を要求していない場合に限ります(OSvに切り替え可能な仮想コンソールはありません)。

コンソールの使用が競合してもCLIとアプリケーションは正常に動作しますが、出力や入力が入り交じって使えないものになってしまいます。

例えばTomcatCLIを実行する場合は、

git clone https://github.com/cloudius-systems/osv.git
cd osv
git submodule update --init --recursive
make image=tomcat,cli

のようにビルドするとTomcatCLIが同時に起動されるイメージを作る事が出来ます。

Capstanで配布されているイメージとしてcloudius/osvというCLIのみを含んだものがありますが、このイメージではJavaや他の言語ランタイムを一切含んでいないため、簡単にユーザプログラムを追加・実行するのが難しくあまり役に立ちません(※ネイティブバイナリを試すことは簡単にできます)。

CLIの使い方

help

help でコマンド一覧を表示します。
help <コマンド名>でコマンド毎の使い方を表示します。

exit

OSを停止します。poweroffと同じ動作になります。

Unix風コマンド群

cat, cd, date, df, dmesg, echo, free, ls, mkdir, poweroff, reboot, rm, top, uptimeについては同名のUnixコマンド風の動作を行います(引数などがPOSIX準拠になっているわけではありません)。

api

他のコマンド群はREST APIをラップして通常のUnixコマンドなどのように振る舞うのに対し、apiコマンドはユーザが直接REST APIを操作するためのものです。
使い勝手は他のコマンド群に劣りますが、現状ではapiコマンドを経由してしかアクセス出来ない機能が多数存在するため、このコマンドを使う事がほとんど必須になります。

api でos, jvm, networkなどのAPIクラス名の一覧が表示されます。

api <クラス名> でAPIクラスが持つメソッドが表示されます。この時、HTTPメソッド種別が特に書いていない説明の行はGETメソッドで、[POST]と書かれている行はPOSTメソッドになります。

GET以外のHTTPメソッドを実行するには、api -m のように引数を渡す必要があります。

例えばos.rebootを実行する場合は以下のようになります:

# api -m POST os reboot

POSTにパラメータが必要な場合は以下のように「変数名=値」の形式で指定します。

/# api os hostname
osv.local
/# api -m POST os hostname name=osv1

/# api os hostname
osv1

POSTに必要な変数名などの細かい情報はCLIのヘルプには表示されないので、WebブラウザでRESTサーバへ接続してREST APIのドキュメントを読んで下さい。
REST APIのドキュメントは http://:8000/ へアクセスして、左側のRESTのタブを選ぶ事で読むことが出来ます。

常に最新版がアップロードされているとは限りませんが、REST APIのドキュメントはこちらにミラーされています:OSv API

Capstanの使い方

CapstanはGo言語で実装されたOSvのデプロイツールです。
各種アプリケーションを含んだディスクイメージを1コマンドでダウンロードし、ローカルのKVMVirtualBoxなどへデプロイすることが出来ます。

以下に使い方を紹介します。

Capstanの対応環境

対応OSはLinux, Mac, Windowsの3つです。
対応しているハイパーバイザIaaSはQEMU(可能ならKVM)、VirtualBoxVMwareGoogle Compute Engineです。
ハイパーバイザを指定しない場合のデフォルトは、LinuxQEMU(可能ならKVM)、Mac, WindowsVirtualBoxです。

インストール方法

Linux / Mac
curl https://raw.githubusercontent.com/cloudius-systems/capstan/master/scripts/download | bash

コマンドのヘルプ(capstan help)

helpでコマンドの一覧を、help <コマンド名>でコマンドの詳細と引数の説明を読むことが出来ます。

capstan help
capstan help run

リモートイメージの検索(capstan search)

search <アプリ名>でアプリ名を含むリモートイメージの検索を行います。
searchだけで実行すると全てのリモートイメージの一覧を表示します。

capstan search tomcat
capstan search

リモートイメージのダウンロード(capstan pull)

pull <リモートイメージ名>でイメージをダウンロードします。

capstan pull cloudius/osv-tomcat

ダウンロード済みリモートイメージの一覧(capstan images)

ダウンロード済みのイメージ一覧を表示します。
ダウンロード済みのイメージはrunコマンドにより再ダウンロードの必要無く実行出来ます。

capstan images

リモートイメージ・停止済みインスタンスの実行(capstan run)

run <リモートイメージ名>でリモートイメージをダウンロード&実行します。既にダウンロードされている場合はダウンロード済みイメージを使用します。

run <インスタンス名>で停止済みインスタンスを実行します。

引数無しのrunではカレントディレクトリのCapstanfileからbuildコマンドで生成されたインスタンスを実行します。

以下にオプション引数の説明をします。

  • -i <インスタンス名>でインスタンス名の変更を行います。デフォルト値はリモートイメージ名から生成されます。
  • -p <ハイパーバイザ名>でハイパーバイザの指定を行います。有効な値はqemu, vbox, vmw, gceのいずれかになります。Linuxのデフォルト値はqemu、それ以外はvboxです。
  • -m <メモリサイズ>でメモリサイズの変更を行います。デフォルト値は1Gです。
  • -c でCPU数の変更を行います。デフォルト値は2です。
  • -n <ネットワークタイプ>でネットワーク構成の変更を行います。有効な値はnat, bridge, tapのいずれかになります。デフォルト値はnatです。
  • -b <ブリッジ名>でブリッジ先デバイス名の変更を行います。デフォルトネットワークタイプはnatなので使用されませんが、デフォルト値はvirbr0です。
  • -f '<ローカルポート番号>:'でnat環境でのポートフォワード設定を行います。
capstan run cloudius/osv
capstan run -m 4G -c 4 -f '8000:8000' -f '8081:8081' cloudius/osv-tomcat

インスタンスの一覧(capstan instances)

instancesでインスタンスの一覧を表示します。

capstan instances

実行中インスタンスの停止(capstan stop)

stop <インスタンス名>で実行中インスタンスを停止します。

capstan stop cloudius-osv-tomcat

インスタンスの削除(capstan delete)

delete <インスタンス名>でインスタンスを削除します。

capstan delete cloudius-osv-tomcat

OSvでLuaインタープリタを動かす

OSvは、ハイパーバイザやIaaSプラットフォームへアプリケーションをデプロイすることに特化した軽量OSです(※詳しくはこちら)。

OSvでは簡易CLIを実装するためにLua言語が使用されています。
この記事では、CLI以外の任意のLuaプログラムをOSv上で実行してみます。

OSvのビルド

OSvのgitリポジトリからソースコードをcloneします。

git clone https://github.com/cloudius-systems/osv.git
cd osv
git submodule update --init --recursive

OSvに含まれるLuaのビルドスクリプトはliblua.soだけをOSvインスタンスへインストールするようになっており、luaコマンドがインストールされません。
取り敢えずluaコマンドを実行してインタラクティブLuaプログラムを実行してみたいので、以下のようなパッチを当てます。

diff --git a/modules/lua/Makefile b/modules/lua/Makefile
index 64ea417..88ae0e6 100644
--- a/modules/lua/Makefile
+++ b/modules/lua/Makefile
@@ -33,12 +33,13 @@ MAIN=src/liblua.so

 # Local executable used for LuaRocks
 LUA_BIN=$(BDIR)/lua
+LUA_BIN_SO=$(BDIR)/lua.so
 LUA_ROCKS_BIN=$(BDIR)/luarocks

 # List of Lua modules, each module has its own target
 LUA_MODULES=LuaSocket LuaJSON Lua_stdlib LuaFileSystem LuaPath LuaSec

-module: $(MAIN) $(LUA_MODULES)
+module: $(MAIN) $(LUA_MODULES) $(LUA_BIN_SO)

 $(MAIN): $(SRCS)
 	cd src && $(MAKE)
@@ -46,6 +47,10 @@ $(MAIN): $(SRCS)
 $(LUA_BIN): $(MAIN) | $(BDIR)
 	cp src/lua $(LUA_BIN)

+$(LUA_BIN_SO):
+	cd src && gcc -o lua.so lua.o liblua.a -lm -ldl -shared
+	cp src/lua.so $(LUA_BIN_SO)
+
 $(LUA_ARCHIVE): | $(DOWNLOAD)
 	cd $(DOWNLOAD) && \
 	 curl --remote-name --remote-time $(LUA_DOWNLOAD)
diff --git a/modules/lua/module.py b/modules/lua/module.py
index b15ebbc..0d3b6b0 100644
--- a/modules/lua/module.py
+++ b/modules/lua/module.py
@@ -8,3 +8,5 @@ usr_files.add('${OSV_BASE}/modules/lua/out').to('/usr') \
 	.exclude('etc/*') \
 	.exclude('lib/luarocks/**') \
 	.exclude('share/lua/*/luarocks/**')
+
+usr_files.add('${OSV_BASE}/modules/lua/out/bin/lua.so').to('/lua.so')

OSvをLua入りでビルドします。

make image=lua

OSv上でLuaを実行

scripts/run.pyでOSvインスタンスKVM上で起動するとLuaインタプリタが起動してインタラクティブLuaスクリプトが実行出来ます。

./scripts/run.py -n -e /lua.so
OSv v0.16-14-g2514672
eth0: 192.168.122.89
Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
>
>
> print("Hello world")
Hello world
> print(type("Hello world"))
string
> = 1 + 2
3

リモートCLIについて

OSvには簡易シェルとしてLua CLIが用意されていて、capstan経由でLua CLIしか入ってないVMイメージが配布されていたりするのですが、実はこのCLIは全てREST API上に実装されています。

つまり、常にhttp://127.0.0.1:8000/へRESTを送ってシステムのAPIを叩いており、そのままこのCLI実装をOSvの外側に持って行けばリモートCLIとして使う事が出来ます。

そもそもそういう意図で実装されていたのですが、最近までOSvの外側で動かすためのテストと配布イメージ作成が行われていませんでした。

最近になってLinux環境にインストール可能な配布イメージを作成出来るようになったので、ビルド方法・インストール方法・使い方をご紹介します。

リモートCLIのビルド方法

ビルド済みイメージを後述のURLから配布しますので、通常この作業は必要ありません。
ディストリビューションでパッケージを作る用途などにお使い下さい。

なお、このビルド方法は今の所Fedora20でのみ動作が確認されています。

git clone https://github.com/cloudius-systems/osv.git
cd osv
git submodule update --init --recursive
sudo scripts/setup.py
cd modules/cli
make rpm

以上のコマンドでrpmbuild/RPMS/x86_64/osv-cli-1.0-1.fc20.x86_64.rpmRPM形式で、rpmbuild/SOURCES/osv-cli-1.0.tar.gzにtar.gz形式で配布イメージが出力されます。

ビルド済みイメージのダウンロード

osv-cli-1.0-1.fc20.x86_64.rpm
osv-cli-1.0.tar.gz

配布イメージのインストー

RPMの場合
yum install osv-cli-1.0-1.fc20.x86_64.rpm
tar.gzの場合
tar xpf osv-cli-1.0.tar.gz
mv osv-cli-1.0/usr/lib64/osv-cli /usr/lib64
echo "(cd /usr/lib64/osv-cli && exec ./cli \$@)" > /usr/bin/cli
chmod a+rx /usr/bin/cli

使い方

シェル1(OSvを起動)
$ capstan run -n 'bridge' cloudius/osv-tomcat
Created instance: cloudius-osv-tomcat
OSv v0.16
eth0: 192.168.122.72

IPアドレスをメモ。

シェル2(リモートCLIを起動)
$ cli -a http://192.168.122.72:8000
/# ls
dev/             etc/             init/            java/
java.so          libhttpserver.so libtools.so      libuutil.so
libzfs.so        proc/            tmp/             tools/
usr/             zfs.so           zpool.so
/# cat etc/hosts
127.0.0.1 localhost osv.local

/# api os version
v0.16
/#

次回予告

今回はRESTサーバに対するセキュリティ設定(鍵認証設定)、CLIの使い方に言及しなかったので、次回はこのあたりを解説していきます。

追伸

Luaで実装されたRESTベースのシェルってやつのソースコードが読んでみたいという方、このへんです。