Plan9日記

2014-10-14

CentOS 7でOSvを動かすまで

OSvを動かしてみるぞ〜。

git clone https://github.com/cloudius-systems/osv.git

して、README.mdを眺める。scripts/setup.pyで必要なパッケージをインストールするみたいだけど、CentOS用の記述がないので、Fedoraをベースにコードを追加。versionがexact matchなので、マイナーバージョンアップしたらダメだな、これ。まぁ、いいや。

diff --git a/scripts/setup.py b/scripts/setup.py
index 8487c2a..c73891b 100755
--- a/scripts/setup.py
+++ b/scripts/setup.py
@@ -51,6 +51,30 @@ class Fedora(object):
 
     versions = [Fedora_20, Fedora_21]
 
+class CentOS(object):
+    name = 'CentOS Linux'
+    install = 'yum -y install'
+    packages = ['gcc-c++', 'gcc-c++-aarch64-linux-gnu', 'git', 'gdb', 'qemu-img',
+                'qemu-system-x86', 'libvirt', 'maven', 'java-1.7.0-openjdk',
+                'ant', 'autoconf', 'automake', 'boost-static', 'genromfs', 'libtool',
+                'flex', 'bison', 'maven-shade-plugin', 'python-dpkt', 'tcpdump', 'gdb',
+                'gnutls-utils', 'openssl', 'python-requests', 'p11-kit', 'patch', 'wget',
+                'unzip', 'ncurses', 'ncurses-devel', 'libstdc++-static', 'openssl-libs',
+                'openssl-devel'
+                ]
+    ec2_packages = standard_ec2_packages
+    test_packages = ['openssl-devel']
+    ec2_post_install = standard_ec2_post_install
+
+    class CentOS_7(object):
+        packages = []
+        ec2_packages = []
+        test_packages = []
+        ec2_post_install = None
+        version = '7.0.1406'
+
+    versions = [CentOS_7]
+
 class Debian(object):
     name = 'debian'
     install = 'apt-get -y install'
@@ -105,6 +129,7 @@ class Ubuntu(object):
 distros = [
            Debian(),
            Fedora(),
+           CentOS(),
            Ubuntu()
            ]

あとは、README.mdに従うだけだけど、makeで止まった。なにやら途中でqemuを起動しているのだが、CentOSにはqemu-system-x86_64コマンドがない(代わりに/usr/libexec/qemu-kvmがある)のが問題のようだ。次のようにworkaround。

$ sudo ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-system-x86_64

scripts/run.pyを実行すると、驚くほどあっさりOSvが起動する。ちなみに-nオプションを付けると、ネットワークが有効になる。デフォルトでは192.168.122.0/24からDHCPIPアドレスが払い出される。-vオプションでvhostを使った高速化が有効になる。

$ sudo ./scripts/run.py -nv
OSv v0.13-53-ge31c3dd
DMI: error
eth0: 192.168.122.89
/# help
COMMAND DESCRIPTION
api     execute arbitrary OSv API operations as defined by the schema
cat     concatenate files and print on the standard output
cd      change the shell working directory
date    print the system date and time
df      report file system disk space usage
dmesg   print operating system boot log
echo    display a line of text
exit    close shell and exit
free    display amount of free and used memory in system
hello   a command example
help    list console available commands and show help
ls      list directory contents
mkdir   make directories
rm      remove files or directories
top     display OSv threads
/# 
/# hello
Hello, OSv!

/proc/self/mapsを見て、luaの共有ライブラリがリンクされているので気付いたのだけど、このシェルluaで実装されているのね。

/# cat /cli/commands/hello.lua
--[[
Commands are expected to be Lua modules.
This file is an example of such a module.
For more on Lua modules, see: http://lua-users.org/wiki/ModulesTutorial
]]--

local cmd = {}

cmd.desc = [[a command example]]
cmd.hello = [[Usage: hello

A command example.]]

--- Called when the command is executed
-- @param args List of arguments from the command line
cmd.main = function(args)
	print("Hello, OSv!")
end

return cmd

dmesgを見えるとどんなデバイスが登録されているかわかる。

/# dmesg
dmesg
4 CPUs detected
Firmware vendor: Seabios
bsd: initializing - done
VFS: mounting ramfs at /
VFS: mounting devfs at /dev
RAM disk at 0x0xffff800002796040 (4096K bytes)
net: initializing - done
vga: Add VGA device instance
eth0: ethernet address: 52:54:00:12:34:56
virtio-blk: Add blk device instances 0 as vblk0, devsize=10842275840
random: virtio-rng registered as a source.
random: intel drng, rdrand registered as a source.
random: <Software, Yarrow> initialized
VFS: unmounting /dev
VFS: mounting zfs at /zfs
zfs: mounting osv/zfs from device /dev/vblk0.1
VFS: mounting devfs at /dev
VFS: mounting procfs at /proc
random: device unblocked.
program zpool.so returned 1
BSD shrinker: event handler list found: 0xffffa0000199e500
	BSD shrinker found: 1
BSD shrinker: unlocked, running
[I/43 dhcp]: Waiting for IP...
[I/246 dhcp]: Server acknowledged IP for interface eth0
[I/246 dhcp]: Configuring eth0: ip 192.168.122.89 subnet mask 255.255.255.0 gateway 192.168.122.1 MTU 1500
Running from /init/30-auto-00: /libhttpserver.so &!

シェルだとできることは限られているのだけど、REST API経由でいろいろ弄れるのが今っぽい。ブラウザhttp://192.168.122.89:8000/を開く。あ、ブラウザ経由でリブートやシャットダウンもできちゃった。面白い。ちなみにコンソールからシャットダウンするときは、exit (or Ctrl-a x)でOK。

2014-09-24

[] brewでGo言語をインストール

A Tour of Goを進んでいくと、HTTPサーバの例が。お、Playgroundで通信ができるのか?と思ったら、案の定、ローカルで実行せよとのこと。

というわけで、brewインストール

$ brew update
$ brew install go
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/go-1.3.1.mavericks.bottle.1.tar
######################################################################## 100.0%
==> Pouring go-1.3.1.mavericks.bottle.1.tar.gz
==> Caveats
As of go 1.2, a valid GOPATH is required to use the `go get` command:
  http://golang.org/doc/code.html#GOPATH

`go vet` and `go doc` are now part of the go.tools sub repo:
  http://golang.org/doc/go1.2#go_tools_godoc

To get `go vet` and `go doc` run:
  go get code.google.com/p/go.tools/cmd/godoc
  go get code.google.com/p/go.tools/cmd/vet

You may wish to add the GOROOT-based install location to your PATH:
  export PATH=$PATH:/usr/local/opt/go/libexec/bin

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completion has been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
  /usr/local/Cellar/go/1.3.1: 4341 files, 114M

コメントに従って、.bash_profileに環境変数の設定を追加。

export GOPATH=$HOME/go
export GOROOT=/usr/local/opt/go/libexec
export PATH=$PATH:$GOPATH/bin:$GOROOT/bin

bashの補完も効くようなので、続けてbash-completionをインストール

$ brew install bash-completion
==> Downloading http://bash-completion.alioth.debian.org/files/bash-completion-1.3.tar.bz2
######################################################################## 100.0%
==> Patching
patching file bash_completion
==> ./configure --prefix=/usr/local/Cellar/bash-completion/1.3
==> make install
==> Caveats
Add the following lines to your ~/.bash_profile:
  if [ -f $(brew --prefix)/etc/bash_completion ]; then
    . $(brew --prefix)/etc/bash_completion
  fi

Homebrew's own bash completion script has been installed to
  /usr/local/etc/bash_completion.d

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d
==> Summary
  /usr/local/Cellar/bash-completion/1.3: 188 files, 1.1M, built in 6 seconds

こちらもコメントに従って.bash_profileに次の記述を追加。ちゃんと補完が効くようになった。

if [ -f $(brew --prefix)/etc/bash_completion ]; then
  . $(brew --prefix)/etc/bash_completion
fi

デフォルトでパッケージ管理システムが組み込まれている訳ね。ドキュメントをインストールしておく。Mercurialを使うので、これも前もってbrew install hgで入れておく。環境変数GOROOT以下にgodocというコマンドがインストールされた。

$ go get code.google.com/p/go.tools/cmd/godoc

はい、ちゃんとHTTPサーバの例題が動きましたとさ。

$ go build 57.go
$ ./57

また、"code.google.com/p/go-tour/wc"のようなパッケージをimportしている例題もあるけど、これをローカルで動かすときは、これもgo getしてくればよい。

$ go get code.google.com/p/go-tour/wc

$GOPATH/src以下にソースコードが、$GOPATH/pkg以下に*.a形式のバイナリパッケージが配置される。

ということで今日は#58まで。

ちなみにCentOS 7のパッケージではGo 1.2になるようだ。

2014-09-06

systemdについて

前回の続きで、systemdを少し調べてみる。systemdはsysvinitに代わってRedhatやDebianで採用されているが、「Linus様がSystemdにぶちきれる」とかboycott systemdとか、物議を醸しているようだ。

CentOS 6.5だと、PID 1は当然initだけど、CentOS 7はsystemdになっているのがわかる。

$ pstree -h
init─┬─acpid
     ├─agetty
     ├─crond
     ├─6*[mingetty]
     ├─ntpd
     ├─rpc.statd
     ├─rpcbind
     ├─rsyslogd───3*[{rsyslogd}]
     ├─sshd───sshd───sshd───bash───pstree
     └─udevd───2*[udevd]
[vagrant@localhost ~]$ pstree
systemd─┬─NetworkManager─┬─dhclient
        │                └─3*[{NetworkManager}]
        ├─VBoxService───7*[{VBoxService}]
        ├─agetty
        ├─auditd───{auditd}
        ├─avahi-daemon───avahi-daemon
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─firewalld───{firewalld}
        ├─iprdump
        ├─iprinit
        ├─iprupdate
        ├─lvmetad
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───5*[{polkitd}]
        ├─rsyslogd───2*[{rsyslogd}]
        ├─sshd───sshd───sshd───bash───pstree
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        └─tuned───4*[{tuned}]

/sbin/initがsystemdへのシンボリックリンクになっているのね。

[vagrant@localhost ~]$ ls -l /sbin/init 
lrwxrwxrwx. 1 root root 22 Aug  1 08:41 /sbin/init -> ../lib/systemd/systemd

systemdは高速起動が売りの一つとのことだけど、systemd-analyzeってコマンドで起動時間や何処で時間を食っているかなどを調べることができる。

[vagrant@localhost ~]$ systemd-analyze time
Startup finished in 431ms (kernel) + 1.326s (initrd) + 7.844s (userspace) = 9.603s

[vagrant@localhost ~]$ systemd-analyze blame
          2.167s firewalld.service
          1.825s kdump.service
          1.584s tuned.service
          1.442s vboxadd.service
          1.166s network.service
          1.102s lvm2-monitor.service
          :

また、ログ周りもsyslogdからjournaldという独自の実装に変わっている。

[vagrant@localhost ~]$ sudo journalctl
-- Logs begin at Fri 2014-09-05 01:45:16 EDT, end at Sat 2014-09-06 00:32:19 EDT. --
Sep 05 01:45:16 localhost.localdomain systemd-journal[80]: Runtime journal is using 4.0M (max 24.5M, leaving 36.7M of free 241.1M, current limit 24.5M).
Sep 05 01:45:16 localhost.localdomain systemd-journal[80]: Runtime journal is using 4.0M (max 24.5M, leaving 36.7M of free 241.1M, current limit 24.5M).
Sep 05 01:45:16 localhost.localdomain kernel: Initializing cgroup subsys cpuset
Sep 05 01:45:16 localhost.localdomain kernel: Initializing cgroup subsys cpu
Sep 05 01:45:16 localhost.localdomain kernel: Initializing cgroup subsys cpuacct
Sep 05 01:45:16 localhost.localdomain kernel: Linux version 3.10.0-123.6.3.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.2 20140120 (Red Hat 4.8.2-16) (GCC) ) #1 SMP Wed Aug 6 21:12:36 UTC 2014
Sep 05 01:45:16 localhost.localdomain kernel: Command line: BOOT_IMAGE=/vmlinuz-3.10.0-123.6.3.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=centos/swap vconsole.font=latarcyrheb-sun16 vconsole.keymap=jp106 rd.lvm.lv=centos/root crashkernel=auto rhgb quiet LANG=en_US.UTF-8
:

オプションに"-b"を指定すればブート時のもの、_SYSTEMD_UNIT=sshd.serviceまたは'which sshd'(デーモンのパス)を指定すればそのログのみが取り出せる。

[vagrant@localhost ~]$ sudo journalctl _SYSTEMD_UNIT=sshd.service
-- Logs begin at Fri 2014-09-05 01:45:16 EDT, end at Sat 2014-09-06 00:34:34 EDT. --
Sep 05 01:45:24 localhost.localdomain sshd[1099]: Server listening on 0.0.0.0 port 22.
Sep 05 01:45:24 localhost.localdomain sshd[1099]: Server listening on :: port 22.
Sep 05 01:45:30 localhost.localdomain sshd[2202]: Accepted publickey for vagrant from 10.0.2.2 port 49275 ssh2: RSA dd:3b:b8:2e:85:04:06:e9:ab:ff:a8:0a:c0:0
Sep 05 01:48:34 localhost.localdomain sshd[3895]: Accepted publickey for vagrant from 10.0.2.2 port 49326 ssh2: RSA dd:3b:b8:2e:85:04:06:e9:ab:ff:a8:0a:c0:0

systemdのメインコマンドはsystemctl。これでサービス(systemd用語ではユニットというのかな)の有効・無効などを制御できる。serviceコマンドのレベルでは互換性を保っているようなので、取りあえずは戸惑いなく使えるのかなぁ。それに加えて、systemctl rebootとかpoweroffってのもできる。ふむ、/usr/sbin/rebootなどがsystemctlへのシンボリックリンクになっている。結構システム全体に影響あるんだなぁ。

あと話は脱線するけど、systemd-detect-virtというハイパーバイザを認識するコマンドがある。

[vagrant@localhost ~]$ systemd-detect-virt 
oracle

どんな実装になっているのかな。gitリポジトリを眺めてみたところ、このへんだね。CPUIDやDMIを使って検出するようね。VirtualBoxの場合は、/sys/class/dmi/id/sys_vendorが"innotek GmbH"であれば、VirtualBoxと判定されるようだ。

関連して、hostnamectlってコマンドもあるようだ。Chassisは"vm"になりそうなものの、"n/a"になっているね。

[vagrant@localhost ~]$ sudo hostnamectl 
   Static hostname: localhost.localdomain
         Icon name: computer
           Chassis: n/a
        Machine ID: 42223b0ecc4b406f8c15a34a4ad16be9
           Boot ID: c140fb95493041e7ab58a6ddbe4b74f6
    Virtualization: oracle
  Operating System: CentOS Linux 7 (Core)
       CPE OS Name: cpe:/o:centos:centos:7
            Kernel: Linux 3.10.0-123.6.3.el7.x86_64
      Architecture: x86_64

2012-07-23

Open vSwitchをKVM環境で使う

ここ以来、なかなかコードを読めていないのだけど、とりあえず環境を作ったので、忘れる前にメモ。まずはOpen vSwitchをLinux標準のブリッジの代わりに使うことを考える。Open vSwitchのバージョンはv1.6.1。OSはDebian GNU/Linux 7.0 (testing)。Debianのパッケージ(1.4.2ベース)は使わずに野良ビルド。

ここに書いたことはトップディレクトリ直下にあるINSTALL.LinuxとINSTALL.KVMの抜粋なので、まずはそこに目を通すべし。

Open vSwitchの構成

基本的な構成要素は次の三つ。Open vSwitchデーモン(ovs-vswitchd)、構成情報を管理するDBサーバ(ovsdb-server)、パケットの転送処理(データパス)を行うカーネルモジュール(openvswitch_mod.ko)である。ovs-switchdとovsdb-serverはUNIXドメインソケットなどで接続される。brctl互換に振る舞うためのovs-brcompatdとbrcompat_mod.koなども存在するがここでは割愛する。

ovs-vsctlコマンドなどを実行したときの制御フローは、ovs-vsctl -> ovsdb-server -> ovs-vswitchd -> openvswitch_mod.koとなるようだ。

インストール

gitからコンパイルする。

$ git clone git://openvswitch.org/openvswitch
$ cd openvswitch
$ git checkout -b v1.6.1 v1.6.1
$ ./boot.sh
$ ./configure --prefix=/opt --with-linux=/lib/modules/`uname -r`/build
$ make
$ sudo make install
$ sudo insmod datapath/linux/openvswitch_mod.ko

ovs-vswitchdの前にovsdb-serverを起動する必要がある。初めて起動するときは、まずovsdb-toolを使ってDBを初期化する。

$ sudo mkdir -p /opt/etc/openvswitch
$ sudo ovsdb-tool create /opt/etc/openvswitch/conf.db vswitchd/vswitch.ovsschema

ovsdb-serverの起動(SSLサポートなしの場合)。

$ sudo ovsdb-server --remote=punix:/opt/var/run/openvswitch/db.sock \
                     --remote=db:Open_vSwitch,manager_options \
                     --pidfile --detach

次に、ovs-vswitchdを起動すればいいのだけど、初回起動時にはDBの処理化のおまじないが必要になる。

$ sudo ovs-vsctl --no-wait init

$ sudo ovs-vswitchd --pidfile --detach

これで準備は完了。

ブリッジの作成

brctlと考え方は同じ。ブリッジbr0を作り、物理デバイスeth1をつなぐ場合は次の通り。

$ sudo ovs-vsctl add-br br0
$ sudo ovs-vsctl add-port br0 eth1

KVMの設定

tapデバイスをブリッジにつなぎこむ場合、「-net tap,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown」のようにスクリプトを実行していると思うが、このスクリプトを以下のようなものに差し替えればOK。これでQEMU/KVM起動時にtapデバイスの着脱が自動的に実行される。

$ cat /etc/ovs-ifup
#!/bin/sh

switch='br0'
/sbin/ip link set $1 up
/opt/bin/ovs-vsctl add-port ${switch} $1
$ cat /etc/ovs-ifdown
#!/bin/sh

switch='br0'
/sbin/ip link set $1 down
/opt/bin/ovs-vsctl del-port ${switch} $1

ovs-vsctl showコマンドで構成を確認することができる。ovs-vsctl list-brとova-vsctl list-ports br0でも同様な結果が得られる。

$ sudo ovs-vsctl show
01f36f74-52d7-4726-a143-28eb85439345
    Bridge "br0"
        Port "eth1"
            Interface "eth1"
        Port "tap0"
            Interface "tap0"
        Port "br0"
            Interface "br0"
                type: internal

この状態でもOpenFlowのフローベースでスイッチングされている。OpenFlowコントローラとは接続してないけど、ovs-ofctlコマンドを使ってフローテーブルを設定することができる。例えば、ovs-ofctlコマンドでフローテーブルを見ると、フローテーブルにはNORMALアクションのエントリが一つだけあることがわかる。

$ sudo ovs-ofctl dump-flows br0
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=6988.236s, table=0, n_packets=25756163, n_bytes=30708661340, idle_age=0,priority=0 actions=NORMAL

終了方法

Debianパッケージだとちゃんとrc.dスクリプトが準備されていると思うけど、pidファイルをcatしてkillすればOK。

$ sudo kill `cd /opt/var/run/openvswitch && cat ovsdb-server.pid ovs-vswitchd.pid`

2012-05-17

カーネルモジュールだけをコンパイルする方法(Debian GNU/Linux

なんかしばらくすると忘れていたのでメモを残しておく。

linux-source-2.6.32パッケージをインストールしておくと、/usr/src/linux-source-2.6.32.tar.bz2がインストールされる。これを展開して、カーネル全体ではなく、例えばKVMだけといった具合に必要なモジュールだけをコンパイルしたい。

# cd linux-source-2.6.32
# cp /boot/config-2.6.32-5-amd64 .config
# make oldconfig
# make modules_prepare
# cp /lib/modules/`uname -r`/build/Modules.symvers .

これで準備が完了。あとはKVMをコンパイルする。

# cd arch/x86/kvm
# make -C /usr/src/linux-source-2.6.32 M=`pwd` modules
# make -C /usr/src/linux-source-2.6.32 M=`pwd` modules_install

(追記:2013-05-10)CentOSでも基本的に同じ。kernel-develパッケージにModules.symversが入っている。