2010/01/30

引き続きDebian lennyでkeepalivedを使ってみる

前回に引き続き、今回はhttp専用サーバを増やしてみました。 前回導入したapacheはアンインストールしています。

今回のサーバー構成図

keepalivedを導入しているサーバ

  • 10.0.0.2
  • 10.0.0.3

Apacheを導入しているサーバ

  • 10.0.0.5
  • 10.0.0.6

keepalivedをApacheの側に導入しないところがポイントです。 ただDR構成を取るとApacheの側でもVirtual_IPを認識させるための手間が必ず必要になります。

keepalived側で必要な設定

前回のkeepalived.confの内容にVirtual_IPの80番ポートにきたリクエストを振り分ける設定を加えます。

/etc/keepalived/keepalived.confファイル

vrrp_instance VI {
  state BACKUP
  interface eth1
  garp_master_delay 5
  virtual_router_id 200
  priority 101
  nopreempt
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass XXXXXX
  }
  virtual_ipaddress {
    10.0.0.1/24 dev eth1
  }
}

virtual_server 10.0.0.1 80 {
  delay_loop 10
  lb_algo rr
  lb_kind DR
  protocol TCP
  real_server 10.0.0.5 80 {
    weight 1
    HTTP_GET {
      url {
        path /
        status_code 200
      }
      connect_timeout 5
    }
  }
  real_server 10.0.0.6 80 {
    weight 1
    HTTP_GET {
      url {
        path /
        status_code 200
      }
      connect_timeout 5
    }
  }
}

Apacheサーバ側で必要な設定

今回はDR(Direct Routing)構成を取っているので、パケットの受け手になるApacheサーバ側で、10.0.0.1宛てのパケットを自分のものだと認識させる必要があります。

KLabの方が書かれたLVSをNATからDSRへの中では、iptablesを使う方法が書かれています。

$ sudo /sbin/iptables -t nat -A PREROUTING -d 10.0.0.1 -j REDIRECT

これは始めてみる方法で確かに動きます。 ただ、これはlinuxに特化しているようにみえて一般的なのかどうか自信はありません。 DR構成のように、いわゆるMACアドレス変換を行なう場合には、ループバックアドレスにVirtual_IPを設定することで対応するように思えます。

sudo /sbin/ifconfig lo:0 10.0.0.1 netmask 255.255.255.255

いずれかの設定をすれば良いのですが、恒久的にはinterfacesファイルにlo:0の定義を入れるのが簡単そうです。

/etc/network/interfacesファイル抜粋

auto lo:0
iface lo:0 inet static
  address 10.0.0.1
  netmask 255.255.255.255

2010/02/01追記:
iptablesを使う場合にはinterfacesファイルに次のような一行を加える事で対応する事もできます。
post-up /sbin/iptables -t nat -A PREROUTING -p tcp -d 10.0.30.1 -j REDIRECT
最終的にlo:0の追加かiptablesを使うかは、同時に使用するVirtual_IPの数によって判断するのが良いようです。

debianでiptablesを操作するにはスクリプトを準備して、interfacesファイルのpre-up, post-upを加える必要があるので少し手間がかかります。 iptablesを使う方にアドバンテージがあるのかはわからないです。

2010/02/01追記:
この構成ではクライアントのARPテーブルにVirtual_IP宛てのMACアドレスとして10.0.0.5, 10.0.0.6のMACアドレスが登録されてしまいます。 このためarpリクエストを無視する必要が生じます。 /etc/sysctl.confか/etc/sysctl.d/以下にファイルを作成して次の設定を加えます。

/etc/sysctl.confファイル抜粋

net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth0.arp_announce=2

まとめ

今回は単純にするためのフロントエンドと本来は裏側に隠蔽されているApacheサーバ群を同じセグメントに配置しました。 本格的なテストには、セグメントを分けないと現実味が薄いように思えます。 ただとっかかりには、これぐらいの構成からスタートするのが良いのではないでしょうか。

また、keepalivedのベストプラクティスについて、まだよくわかっていないところがあります。 少なくともVRRPの設定は両方ともpriorityを同一にして、nopreemptを設定し、stateに書く起動時の初期状態はBACKUPにしておくのは良いマナーに思えます。

やはり「制御する」ことを考えると、もう少しOSやkeepalivedの挙動について理解が必要そうです。 iptablesを使ってMACアドレスが書き換えられたパケットを受領するとは、予想できませんでした。

それと「サーバ/インフラを支える技術」は間違いなく良い本だけれど、 必要な事が漏れなく書かれているわけではないので、これだけで何とかしようとする人には向かないでしょう。

ブラックボックスとしての技術だけを導入して問題を解決しようとしてもそれは不十分で、システム全体をぐるっと抱えて挙動を見渡すだけの少し高いところから見る技術が必要になると思います。

2010/01/29

Debian lennyでkeepalivedのHAテスト

技術評論社から出版されている「24時間365日サーバ/インフラを支える技術」をみていて、 LVSとkeepalivedが紹介されていました。 debian系のパッケージにはkeepalivedは登録されていますし、手軽に使えそうです。

今回はkeepalivedを使ったHAクラスタを構成してみます。

VMWare Workstation 6.5上にDebian lennyのインスタンスを3つ立ち上げて、 keepalivedの挙動をみてみました。

サーバー構成

VMWare WorkstationではTeamを組む事でネットワークカードとハブを仮想的に追加できるので、 この手のテストには向いています。

特にネットワークセグメントは分離せずに独立した一つのサブネットワークの中に、2台のサーバ(10.0.0.2, 10.0.0.3)と1台のクライアント(10.0.0.x)を作成しました。 サーバで共有するVirtual_IPは10.0.0.1にしています。

VRRPサーバー構成

keepalivedの設定

まずはapt-getでパッケージが導入しました。

$ sudo apt-get install keepalived

設定ファイルを配置する/etc/keepalivedディレクトリが作成されますが、中身は空です。 本に書かれているように、keepalived.confファイルを準備してみます。

vmweb01mの/etc/keepalived/keepalived.confファイル

vrrp_instance VI {
  state MASTER
  interface eth1
  garp_master_delay 5
  virtual_router_id 200
  priority 101
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass XXXXXX
  }
  virtual_ipaddress {
    10.0.0.1/24 dev eth1
  }
}

片側のvmweb02mにファイルをコピーして、priority 100にだけ変更しておきます。

keepalivedの起動

keepalived.confファイルを配置するとリブートすると起動するようになります。 今回は手動で起動します。

$ sudo /etc/init.d/keepalived start

挙動の確認

keepalivedが起動してからnetstatやifconfigなどで調べても、VIPの10.0.0.1はサーバー上に設定されていません。 ipvsadmの設定も空です。

$ sudo /usr/sbin/ipvsadm -L

ipvsadm -Lコマンドの出力

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

MACアドレスを変更しているのだろうとあたりをつけて、 クライアント側からインタフェースがどのように変更されるのか確認してみました。

$ sudo apt-get install arp-scan

arpコマンドでも良いのですが、動的に変更されるとは限らないのでarp-scanを準備しました。 同一サブネット(10.0.0.0/24)に所属しているクライアントからコマンドを実行します。

$ sudo arp-scan -I eth1 10.0.0.1 10.0.0.2 10.0.0.3

arp-scanコマンド出力

10.0.0.1	00:0c:29:c1:7b:47	VMware, Inc.
10.0.0.2	00:0c:29:c1:7b:47	VMware, Inc.
10.0.0.3	00:0c:29:71:34:69	VMware, Inc.

この出力からIPアドレス10.0.0.1が、10.0.0.2のMACアドレスに属している事がわかります。 10.0.0.2, 10.0.0.3は両サーバのeth1に定義されています。

プライマリ側のkeepalivedを停止

再起動しても良いのですが、ここではkeepalivedを停止する事で接続断を演出してみます。

$ sudo /etc/init.d/keepalived stop

10.0.0.2でのkeepalived停止後のarp-scan出力

10.0.0.1	00:0c:29:71:34:69	VMware, Inc.
10.0.0.2	00:0c:29:c1:7b:47	VMware, Inc.
10.0.0.3	00:0c:29:71:34:69	VMware, Inc.

次に10.0.0.2のkeepalivedを起動して、10.0.0.1がどちら側に移動するか確認します。

$ sudo /etc/init.d/keepalived start

10.0.0.2でのkeepalived起動後のarp-scan出力

10.0.0.1	00:0c:29:c1:7b:47	VMware, Inc.
10.0.0.3	00:0c:29:71:34:69	VMware, Inc.
10.0.0.2	00:0c:29:c1:7b:47	VMware, Inc.

この設定だとpriorityの高い側に自動的に寄るようですね。

pingを使ったパケットロスの確認

keepalivedの切り替えが発生するタイミングでpingを10.0.0.1に送っていると次のようになりました。

64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.200 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.226 ms

64 bytes from 10.0.0.1: icmp_seq=6 ttl=64 time=3.93 ms
64 bytes from 10.0.0.1: icmp_seq=7 ttl=64 time=0.411 ms
64 bytes from 10.0.0.1: icmp_seq=8 ttl=64 time=0.213 ms
64 bytes from 10.0.0.1: icmp_seq=9 ttl=64 time=0.275 ms

64 bytes from 10.0.0.1: icmp_seq=11 ttl=64 time=0.377 ms
64 bytes from 10.0.0.1: icmp_seq=12 ttl=64 time=0.457 ms
...
--- 10.0.0.1 ping statistics ---
13 packets transmitted, 11 received, 15% packet loss, time 12048ms
...

結果としてicmp_seq=5, icmp_seq=10の2つのパケットが取りこぼされています。 仮想MACアドレスが使えれば、パケットの取りこぼしはなくなると思うんですけどね…。

Apacheを使った挙動の確認

準備作業

とりあえず10.0.0.2と10.0.0.3の両方にapacheをインストールします。

$ sudo apt-get install apache2-mpm-worker

導入した直後にプロセスが起動して、80番ポートで通信を受け付けるはずです。

HTTPサーバのモニター

再送とかタイムアウトの設定とかなしで、かなり乱暴ですが、telnetコマンドを使って80番ポートにアクセスしてみます。 ここでkeepalivedを片側だけ停止しておきます。

$ telnet 10.0.0.1 80
Trying 10.0.0.1...
Connected to vmwebcl01.example.org.
Escape character is '^]'.

次にkeepalivedを停止してから、telnetコマンドを同じように実行します。

$ telnet 10.0.0.1 80
Trying 10.0.0.1...

しばらく停止しているので、ここで最初から停止していたkeepalivedを起動します。 するとプロンプトが表われるので、HTTPプロトコルを送信します。

Trying 10.0.0.1...
Connected to vmwebcl01.example.org.
Escape character is '^]'.
HEAD / HTTP/1.0

...

2回目のtelnetコマンドを実行してすぐに通信が途切れないのはTCPレベルで再送が行なわれているからですが、telnetコマンドを実行した時点では直近で起動していたkeepalivedのホストのMACアドレスを覚えています。

最後にkeepalivedを起動した時には、新しく10.0.0.1のMACアドレスとして通知された側に接続しています。 表面上は少し待たされたものの、何事もなかったのかのように処理が進みます。

まとめ

keepalivedを上げ下げする時には、途中でarp-scanを実行したり、tcpdumpの"-w"オプションで経過をファイルに保存しておいて、別マシンのwiresharkで表示してみるとSYNパケットが繰り返し送信されている様子をみる事ができると思います。 現場ではarpかarp-scanぐらいしか使えないかもしれないですが、 学習目的ではtcpdumpとwiresharkは使えると便利ですし楽になるはずです。

ICMPパケットはロストしますが、TCP/IPは再送で救われる場面がありそうです。 現場での疎通確認をpingだけに頼っていると、ちょっと見誤ることはあるかもしれません。 もっともこの構成だと救われるのは新規のコネクションに限定した話しで、既存のコネクションは切れてしまうのが悩みどころです。

keepalivedは簡単にVirtual-IPを設定できるという点では便利だと思います。 冗長化するためのツールとしてはheatbeatも有名で豊富な機能を提供していますが、ちょっと面倒なようです。

2010/01/25

Alix用にDebian LennyなCFカードを作成する

今回の作業はUbuntu 9.10用のCFカードを作る手順と、ほぼ同じです。 以前に簡単なメモを残しましたが、いろいろ手順が抜けていて使いづらかったので新たに作成する機会にメモを取り直しました。

今回は重複する具体的な作業手順は省略したいところですが、複数の文書を参照するのは面倒なので、網羅する方向でまとめています。

今回も作業はDesktopなUbuntu 8.04 LTSにUSB経由でCFカードを接続して行なっています。

CFカードへの基本システムの導入

ここはいつも通りの作業で、fdisk, mke2fs, tune2fsを使い、debootstrap+grubでブータブルなCFカードを作成します。

$ sudo /sbin/fdisk /dev/sdg
$ sudo /sbin/mke2fs -j /dev/sdg1
$ sudo /sbin/tune2fs -c 0 -i 0 /dev/sdg1
$ sudo mount /dev/sdg1 /mnt/cf
$ sudo debootstrap --arch i386 lenny /mnt/cf
$ sudo grub-install --no-floppy --root-directory=/mnt/cf /dev/sdg

2010/02/25追記:
grub-installコマンドに"--no-floppy"オプションを追加。これで体感的には処理が早く終るようになりました。

実際のブートに必要な最低限の残作業

grubの導入が終ってから/mnt/cfにCFカードをmountしたまま、chrootしてから作業を行ないます。

$ sudo chroot /mnt/cf /bin/bash
apt-get周りの設定

sources.listファイルを編集します。

# vi /etc/apt/sources.list

/etc/apt/sources.listファイル

deb http://ftp.jp.debian.org/debian/ lenny main
deb-src http://ftp.jp.debian.org/debian/ lenny main

deb http://security.debian.org/ lenny/updates main
deb-src http://security.debian.org/ lenny/updates main

deb http://volatile.debian.org/debian-volatile lenny/volatile main
deb-src http://volatile.debian.org/debian-volatile lenny/volatile main
# apt-get update
カーネルの導入

Ubuntuとは名前が違うので、最新にするためlinux-image-2.6-686を導入します。 もしWRAPにするのなら-486にしてください。

# apt-get install linux-image-2.6-686

2010/02/24追記:
ここでは質問が画面上に出力されるので、次のように選択します。
「Create a symbolic link to the current kernel image? 」にはYes
「Abort initrd kernel image installation?」にはNo

kernel-img.confファイルを事前に準備しておきます。

# vi /etc/kernel-img.conf

/etc/kernel-img.conf

# Kernel Image management overrides
# See kernel-img.conf(5) for details
do_symlinks = Yes
do_bootloader = no
do_initrd = yes
postinst_hook = update-grub
postrm_hook   = update-grub
grub周りの設定
# apt-get install grub
# vi /boot/grub/menu.lst

/boot/grub/menu.lstファイルの内容

serial --speed=38400
terminal serial
##
default         0
timeout         10
##
title           Debian lenny
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.26-2-686 root=/dev/hda1 console=ttyS0,38400n8
initrd          /boot/initrd.img-2.6.26-2-686
savedefault

2010/02/24追記:
menu.lstファイルに書かれている"vmlinuz-*"、"initrd.img-*"が実際に存在している事を確認します。
例えば、次のようなコマンドで/bootで始まるファイルを抜き出して存在するかどうか、lsコマンドでチェックできます。

# tr ' ' '\n' <  /boot/grub/menu.lst | grep boot | xargs ls

成功した場合の出力例

/boot/initrd.img-2.6.26-2-686  /boot/vmlinuz-2.6.26-2-686

失敗した場合の出力例(-486なカーネルをインストールした場合)

ls: cannot access /boot/vmlinuz-2.6.26-2-686: No such file or directory
ls: cannot access /boot/initrd.img-2.6.26-2-686: No such file or directory
シリアル端末周りの設定

inittabファイルを編集します。tty[1-6]を起動する行をコメントアウトし、ttyS0の行のコメントを外します。 ttyS0の通信速度は38400に変更します。

# vi /etc/inittab

/etc/inittabファイル抜粋

...
#1:2345:respawn:/sbin/getty 38400 tty1
#2:23:respawn:/sbin/getty 38400 tty2
#3:23:respawn:/sbin/getty 38400 tty3
#4:23:respawn:/sbin/getty 38400 tty4
#5:23:respawn:/sbin/getty 38400 tty5
#6:23:respawn:/sbin/getty 38400 tty6
...
T0:23:respawn:/sbin/getty -L ttyS0 38400 vt100
...
fstabファイルの編集

起動時に'/'がみつけられないと起動できないので、fstabファイルを作成しておきます。

# vi /etc/fstab

/etc/fstabファイル全体

/dev/hda1 / ext3 defaults,relatime 0 0
proc /proc proc defaults 0 0
USB経由での作業終了

ここまではデスクトップにUSBカードリーダを接続して作業しました。 ここから先はalixで起動し、シリアル経由で接続して作業を進めます。

# exit
$ sudo umount /mnt/cf

umountコマンドが成功してからCFカードを引き抜き、alixに入れて電源を接続します。

シリアル経由でのAlixでのセットアップ作業

まずはシリアル端末を使って、ネットワークへの接続と必要なパッケージの導入などを行なっていきます。

2010/02/24追記:
この中でinterfacesファイルを作成する作業はCFカードをマウントしてファイルを編集することができます。
その他の作業もあらかじめ行なっておく事は可能ですが、面倒な状況になりそうなのでAlix側で作業を行なっています。

ネットワークへの接続

interfacesファイルを編集します。

# vi /etc/network/interfaces

/etc/network/interfacesファイル

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address 192.168.10.10
  netmask 255.255.255.0
  gateway 192.168.10.1

システムを再起動するか、ifupでインタフェースを起動します。

# ifup lo
# ifup eth0
遠隔操作に必要なパッケージの導入

openssh-serverとsudoの準備をします。

# apt-get install openssh-server sudo

sudoは設定ファイルを編集しますが、必ずvisudoコマンドを使います。 手動でsudoersファイルを編集してはいけません。 また、これは状況によりますが、ここではroot権限のみを与えますが、パスワード無しでの操作は許可しないようにします。

# visudo

visudoで追加する設定

%sudo ALL=ALL
作業用IDの作成
# useradd -G sudo -m user01
# passwd user01
シリアル経由での作業完了

ここまでネットワーク経由でのsshログインができるようになったので、 これ以降の作業はSSH経由で行ないます。

SSH経由でのalix設定作業

パッケージの更新

更新が終り次第、システムを再起動します。

$ sudo apt-get dist-upgrade
$ sudo /sbin/shutdown -r now

再度ログインし、作業を続けます。

時刻関連の修正

locale, timezone, ntpと日付、時刻に関連する変更作業を行ないます。 まずは時刻をUTCからJSTへ変更します。

$ sudo rm /etc/localtime
$ sudo ln -s /usr/share/zoneinfo/Japan /etc/localtime

続いてlocale周りの修正を行ないます。

$ sudo apt-get install locales
$ sudo /usr/sbin/dpkg-reconfigure locales

画面にメニューが表われるので、ja_JP.UTF-8を選択します。 デフォルトのlocaleはNoneを選択します。

最後にntpの設定です。 LANの中に自前のntpサーバー(192.168.1.2)があるので、これを指定します。

$ sudo apt-get install ntpdate openntpd

/etc/default/ntpdateファイル

...
NTPDATE_USE_NTP_CONF=no
...
NTPSERVERS="192.168.1.2 ntp.ring.gr.jp"
...

ntp.confファイルは設定を全てコメントアウトし、下記の1行だけを加えます。

/etc/openntpd/ntpd.conf

...
server 192.168.1.2
...

/etc/default/openntpd

DAEMON_OPTS="-s"
ホスト名の変更

適当な名前をつけて/etc/hostnameに1行で書きますが、sudoが逆引きできるように、(例えば"lenny"といった)名前を/etc/hostsに登録しておきます。

$ sudo vi /etc/hostanme

/etc/hostnameファイル

lenny
$ sudo vi /etc/hosts

/etc/hostsファイル

127.0.0.1 localhost lenny
::1 localhost lenny

grubで使っている/boot/grub/menu.lstを編集します。

$ sudo /usr/sbin/update-grub
$ sudo vi /boot/grub/menu.lst

/boot/grub/menu.lstファイルの変更個所の抜粋

...
default         1
...
# kopt=root=/dev/hda1 console=ttyS0,38400n8
...

変更した内容が反映されるように再度update-grubコマンドを実行します。

$ sudo /usr/sbin/udpate-grub

kernel行の最後に追加したconsole=ttyS0,38400n8が書かれている事を確認します。

さいごに

おおよそここに挙げたような設定で、lennyを使うための土台はできるはずです。

繰り返しの作業が嫌な場合には、ここでddコマンドを使ってセットアップしたイメージを保存しておきましょう。 同じくddで同容量の別のCFカードにコピーすれば、すぐに使えるようになります。

$ sudo dd if=/dev/sdg of=lenny_cf.img bs=512

AlixでXG-601を使って無線LAN APを作ってみる

XG-601なカードを調べてみる

XG-601のスペックは以前調べていて、WEPまでの対応と書かれていました。 WPAに対応するためにはハードウェアサポートが必須だと思っていたのですが、ここに勘違いがあったようです。

たまたまマイコミの森井教授の記事を眺めていてWPA-TKIPはWEPとほぼ互換な機能だとありました。 これならソフトウェアだけで動くのかもしれないと思い、alixにXG-601を装着して無線LANクライアントとhostapdによるAP(Access Point)化を試してみました。

Lennyでの無線LAN環境の構築

とりあえず次のようなパッケージを導入しました。

  • wireless-tools
  • wpasupplicant
  • libnl-dev
  • bridge-utils

hostapdはパッケージだと0.5.xで古いので、hostapdの配布元からダウンロードしてコンパイルする事にしました。 最終的に開発版のhostapd-0.7.1.tar.gzを使って動かしています。

hostapdのコンパイルをalix上で行なうのであれば、build-essentialパッケージで一括か、gcc, make libc6-devパッケージを個別にインストールするのが良いと思われます。

Debian lennyとXG-601で無線LANを使うための作業と資料

Ubuntuではfirmwareなどが準備に準備されているため追加の作業は必要ありません。 firmwareは無線LANカードに搭載されたMIPSやARMといったCPU用のバイナリコードです。

Debian lennyではこのfirmwareが準備されていないため自前で配置します。 以前調べた時にみつけた参考資料として、debianでのprism系無線LANドライバを使うためのドキュメントがあります。 lennyで試す時にp54pciドライバが読み込むfirmwareを/lib/firmwareディレクトリに配置しました。

$ sudo wget -O /lib/firmware/isl3886 http://daemonizer.de/prism54/prism54-fw/fw-softmac/lmac_2.7.0.0.arm
$ sudo wget -O /lib/firmware/isl3886pci http://daemonizer.de/prism54/prism54-fw/fw-softmac/2.13.12.0.arm

このファイルを読み込ませるためには、p54pciモジュールを削除してから再度読み込ませるか、システムをリブートします。

$ sudo /sbin/modprobe -r p54pci
$ sudo /sbin/modprobe p54pci
クライアントとして起動

まずはhostapdを使わず、クライアントとして動かすために/etc/network/interfacesファイルを編集しました。

以前書いたUbuntu 9.10を無線LANクライアントにする記事を参考にinterfacesファイルの設定をコピーしています。 インタフェースはwlan0という名前なので、ra0となっていた個所はwlan0で書き換えました。 その他はssidwpa_passphraseを書き換えて、設定ファイルを閉じたらifupを使ってインタフェースを起動します。

$ sudo ifup wlan0

これでlenny付属のカーネル2.6.26-2-486では問題なく動きました。 ここまでは順調なんですよね。すくなくともクライアントとして動かす分には問題なさそうです。

XG-601を使った無線LAN APの構築

いよいよ本命のXG-601 AP化にとりかかってみます。

br0インタフェースの準備

他のAP構築を説明する記事では、wlan0自体にはIPアドレスを割り当てず、eth0とブリッジするためにbr0をよく使っています。

もしbr0を使わない方法も考えられて、wlan0にIPアドレスを割り当ててゲートウェイとして使う事で、無線LANクライアントをNATで閉じ込めるか、wlan0をデフォルトゲートウェイとするサブネットワークを構成するといった対応があると思います。 いずれにしても新たにサブネットワークを準備する必要性がないので、eth0が接続されている既存の192.168.10.0/24の一部として無線LANクライアントを構成する事にしました。

interfacesファイルを編集しますが、必ずbridge-utilsパッケージを導入してください。

変更前:/etc/network/interfaces

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address 192.168.10.10
  netmask 255.255.255.0
  gateway 192.168.10.1

変更:/etc/network/interfaces

auto lo
iface lo inet loopback

auto br0
iface br0 inet static
  address 192.168.10.10
  netmask 255.255.255.0
  gateway 192.168.10.1
  bridge_ports eth0 wlan0

ここで一度システムを再起動して、br0に192.168.10.10のアドレスが割り当てられるか確認します。

hostapdをコンパイル

開発版のhostapd-0.7.10を準備しました。 コンパイルの手順はどちらも同じです。

$ tar xvzf hostapd-0.7.1.tar.gz
$ cd hostapd-0.7.1/hostapd
$ cp defconfig .config
$ vi .config
$ make

$ diff defconfig .configの結果

23c23
< #CONFIG_DRIVER_NL80211=y
---
> CONFIG_DRIVER_NL80211=y

最終的にはデーモンとして起動しますが、設定途中でメッセージを端末に出力しつつ動作を確認する(-ddオプション)には次のように動かします。

$ cd ~/hostapd-0.7.1/hostapd
$ sudo ./hostapd -dd hostapd.conf

XG-601なPRISM GTカードは明示的にはサポート対象の中には入っていません。 ただp54pciモジュールはSoftMACに対応しているはずで、driver=nl80211でカバーされる範囲に入っているはずなのでこれを指定したところkernelのバージョンによっては問題なく動きました。

ただp54pciなカードをnl80211として動かすというところが後々の問題の原因なのかもしれません。

lenny+hostapd-0.7.1で稼働するカーネルのバージョン

まずデフォルトの2.6.26ではhostapdは動きませんでした。 安定して動いているのはlinux-2.6.30.10です。

linux-2.6.31がコンパイルすら失敗するのは御愛嬌としても、linux-2.6.31.x〜linux-2.6.33-rc5(mainline)までしばらく動かすとkernel panicを引き起すという現象が発生しています。

linux-2.6.30.10カーネルのコンパイルについては、別の記事(Debian Lennyでのカーネルコンパイル)を参考にしてください。

hostapdの設定ファイル

動きを確認したhostapd.confの設定ファイルは次のようになっています。

$ egrep -v ^# hostapd.conf| grep -v ^$

hostapd.confファイル

interface=wlan0
bridge=br0
driver=nl80211
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=xxxxxxxxxxxx
country_code=JP
ieee80211d=1
hw_mode=g
channel=9
beacon_int=100
dtim_period=2
max_num_sta=255
rts_threshold=2347
fragm_threshold=2346
macaddr_acl=0
auth_algs=3
ignore_broadcast_ssid=0
wmm_enabled=1
wmm_ac_bk_cwmin=4
wmm_ac_bk_cwmax=10
wmm_ac_bk_aifs=7
wmm_ac_bk_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmin=4
wmm_ac_be_cwmax=10
wmm_ac_be_txop_limit=0
wmm_ac_be_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmin=3
wmm_ac_vi_cwmax=4
wmm_ac_vi_txop_limit=94
wmm_ac_vi_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmin=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_txop_limit=47
wmm_ac_vo_acm=0
ieee8021x=0
eapol_key_index_workaround=0
eap_server=0
own_ip_addr=127.0.0.1
wpa=1
wpa_passphrase=xxxxxxxxxxxxxxxxxxxxxxxxx
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
rsn_pairwise=TKIP CCMP
Windows Vistaからアクセスしてみる

デフォルトの2.6.26では起動すらしてくれないので、linux-2.6.32.4を最初に試してみました。

このAPにInspiron 640mのWindows Vista SP2 32bitからアクセスしてみました。 ちゃんとインターネットにも接続できるのですが、linux-2.6.31以降では数分するとkernel panicを起します。

kernel panic時のメッセージ

[  216.410165] BUG: unable to handle kernel paging request at ffffffab
[  216.412286] IP: [<d096f965>] p54_tx+0x545/0x750 [p54common]
[  216.412286] *pde = 0081d067 *pte = 00000000
[  216.412286] Thread overran stack, or stack corrupted
...
[  216.412286] Call Trace:
[  216.412286]  [<c04adf9b>] ? llc_rcv+0x2b/0x2f0
[  216.412286]  [<c049337b>] ? kfree_skb+0x3b/0x80
[  216.412286]  [<c04adf9b>] ? llc_rcv+0x2b/0x2f0
[  216.412286]  [<c049e667>] ? netif_receive_skb+0x367/0x580
[  216.412286]  [<d0912ccf>] ? __ieee80211_tx+0x8f/0xc0 [mac80211]

このメッセージに続くところをみてみると、p54_txのところで問題が発生しているのに呼び出し元はnetif_receive_skbみたいなんですよね。「p54_rxじゃないんだ…」とか思っても、ここら辺の知識はほとんどないのでお手上げです。 メモリリークのスピードが速すぎて観測できないのかもしれないけれど、 skbの取り扱いにバグがあるんじゃないかな…、と思います。

もう手に負えないので、いくつかのバージョンを試してlinux-2.6.30.10は問題もなく、いまのところ安定して動く事がわかりました。

まとめ

結局のところ2.6.30.10では無事に稼働し、2.6.31では無線LAN自体が動きませんでした。 2.6.30.10では安定しているので、これを家の無線LAN APとして使っていこうと思います。 余裕があれば実家にコレガのWLBAR-54GTが余っているので、そこからXG-601を取り出して少しづつバージョンを上げて原因を追っていこうと思います。ま、やっても自分の力じゃ無理な感じがしますけどね。

Debian Lennyでのカーネルコンパイル

alix上でのコンパイルは負荷が高いのでUbuntu 8.04 LTS上のVMWare Workstationにlennyを準備してカーネルのコンパイルができるようにしました。

Debian lennyでのカーネルコンパイル

Debianではカーネルの構築用にいくつかのツールが提供されていますが、今回はmake-kpkgコマンドを使っています。

基本的な手順

make-kpkgを使う時に使う典型的な手順は次の通りです。

2010/03/01追記:
カーネルをビルドする前に、いくつかのパッケージの導入が必要です。 余計なものが入るかもしれませんが、次のようなコマンドラインは便利かもしれません。
$ sudo apt-get install kernel-package bzip2 build-essential

$ sudo tar xvjf linux-2.6.31.1.tar.bz2 
$ cd linux-2.6.31.1
$ cp -i /boot/config-2.6.26-2-686 .config
$ yes "" | sudo make oldconfig
$ sudo make-kpkg clean
$ sudo INSTALL_MOD_STRIP=1 CONCURRENCY_LEVEL=3 make-kpkg --initrd --append-to-version=-686-mybuild kernel_image kernel_headers

もし既存の.configファイルが存在してcpコマンドが質問をしてきた場合にはC-cやnを入力します。 また既にlinux-2.6.30.10などをコンパイルしている場合には、そこで使った.configファイルを持ってきます。 ただし副作用がわからないので2.6.32など、より新しいバージョンの.configファイルは使わないようにしています。

-686-mybuildの部分は、適当に自分に都合に合わせて変更します。

大抵はエラーがでると思いますが、下記のように対応して直近のmake-kpkg ... kernel_imageコマンドを再び実行します。

カーネルバージョン毎に必要な対応手順

lennyでコンパイルするという条件の元では、より新しいカーネルを構築する際にエラーになる場合があります。 その対応方法をまとめました。

2.6.31以降で遭遇するエラー

lenny上で2.6.31以降をコンパイルした時のエラーメッセージ

lguest.c:21:25: error: sys/eventfd.h: No such file or directory
lguest.c: In function ‘create_thread’:
lguest.c:1027: warning: implicit declaration of function ‘eventfd’

2.6.31カーネルをlenny上でコンパイルするためのTipsに従ってMakefileを修正し、無事にカーネルがビルドできました。

$ sudo vi Documentation/lguest/Makefile

修正個所のMakefile抜粋

_FORTIFY_SOURCE

all: 
2.6.33以降で遭遇するエラー

lguestの他の原因で、make-kpkgコマンドが途中で止ってしまいます。

lenny上でのエラーメッセージ

The UTS Release version in include/linux/version.h
	   "" 
does not match current version:
	   "2.6.33-rc5-686-yabuild" 
Please correct this.

対応方法はUbuntuのKernel Master Threadのコメントの中にあります。

$ sudo cp -i include/generated/utsrelease.h include/generated/compile.h include/linux/

debパッケージのインストール

この後で再びmake-kpkgコマンドを走らせると、続きから始まりパッケージが終了します。 一つ上の../ディレクトリにdebパッケージが作成されるので、これをalixにコピーするなどして実行します。

$ sudo dpkg -i linux-image-2.6.32.4-686-yabuild_2.6.32.4-686-yabuild-10.00.Custom_i386.deb

2010/01/21

WLI-MPCI-G54をalixで試してみた

まずはWLI-MPCI-G54を検討

いろいろ調べてましたが、WLA-G54の中古を購入してminiPCIカードとアンテナを取り外して使う事にしました。 このカードはWLI-MPCI-G54(無印)で、linuxではBCM4306 Rev.2用のb43legacyドライバをロードする事で無線LANのクライアントになる事ができます。

一時検討した玄人志向の802.11ND-MPCIカードは、 2009年2月に購入した方のブログによれば、搭載されているチップがBCM4321とのことです。 残念ながらこれはlinuxwireless.orgのb43ドライバ情報によると、まだサポートされていないチップです。

しかし結局はWLI-MCPI-G54でアクセスポイントを作る事はできませんでした。 linuxwireless.orgのWMP54G関連のドキュメントの中で、このカードも含めてBCM4306系カードの中にアクセスポイントになれないものがあるとの記述があります。

リビジョンが違えばb43ドライバが使えそうですし、そこでは問題ないのかもしれませんが、手元にはカードがないのでこれは諦める事にしました。

2010/01/17

Aterm WL54GUをUbuntu 9.10で試してみる

近くの家電量販店でatherosのSuperGに対応しているUSBスティックの Aterm WL54GUを買ってみましたが、Ubuntu 9.10でもそのままでは見事に動きませんでした。

ただ、まったく使えない感じではなかったのでドライバの中にUSBIDを埋め込み、再ビルドして使えないか確認する事にしました。

引き続き無線LANの親機(AP)はCoregaの CG-WLRGNX(W)ですが、ステルスAP機能は無効にしています。

WL54GUを認識させる

WL54GUのなかを開けてみるとチップはAtheros 2524-AQ1Cで、linuxwireless.orgを調べると zd1211rw ドライバを使うようなのですが、modprobeしても動きません。

カーネルの再構築

手元でgitから取り出したUbuntu 9.10 2.6.31-17-genericをベースにzd1211rw/zd_usb.cを編集しました。WL54GUのUSBID(0409:0248)を追加してビルドした版をalixで試したところ、無事に認識してネットワークに接続しました。systemtap用に gitからカーネルをビルドする環境をvmwareに作っておいて役に立ちました。

drivers/net/wireless/zd1211rw/zd_usb.cファイルの追加部分

{ USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B  },

interfacesファイルだけを編集して必要な情報を追加しています。 auto wlan0 行はつけていないので手動でwlan0を起動しています。

/etc/network/interfaces抜粋

iface wlan0 inet static
  address 192.168.1.4
  netmask 255.255.255.0
  gateway 192.168.1.1
  wpa-driver wext
  wpa-ssid xxxxxxxxxxxx
  wpa-ap-scan 1
  wpa-proto WPA
  wpa-pairwise TKIP CCMP
  wpa-group TKIP CCMP
  wpa-key-mgmt WPA-PSK
  wpa-psk xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$ sudo ifup wlan0

いずれにしてもWL54GUはAPモードが動かないのは残念なところです。

zd1211rwドライバへのUSB IDの追加方法

linuxwireless.orgの中に、新しいzd1211rwデバイスの追加手順が書かれていました。 → Adding new device IDs to zd1211rw

new_idファイルを経由する方法は興味深いのですが、今回は飛ばして全体として問題がないか流れを確認しました。 どうも安定していそうなので、USBIDをMLにポストして終りにしようと思います。

2010/01/18追記: zd1211-devに投稿したら、速攻でパッチがメンテナに流れていました。 こういうスピード感がつくづくすごいなと思います。

実験中に無線LANのAPと通信ができなかった理由

ひどい事にCoregaな親機にMACアドレスフィルタを10個追加したら、WL54GUが接続できなくなりました…。

原因にはまるで気がつきませんでしたが、WL54GUのマニュアルには「上限までMACアドレスを登録しない」という注意書きがあって解決しました。 まさかこんな事がおこるとは思いませんでしたが、余計なMACアドレスを削除してからWL54GUの動きに問題がないか確認するはめになりました。

この記事で取り上げた品々

無線LAN AP構築用に情報収集

無線LANのAccess Point (AP)を構築するには、hostapdというソフトウェアを使うのが一般的なようです。 そしてhostapdが対応する無線LANのチップが限定されています。 先日試したrt2870staは名前に"STA"が含まれている事からも、ステーションモード専用でAPにはできません。

そこで、alixを使った無線LAN APに必要なカードや、そこから関連する情報を調べてみました。

とりあえずhostapdについて調べてみた

ここで対応しているのは、Prism系のチップを搭載したものなどがほとんどのようです。 WPAに対応しているとなると、atheros系のチップが入手しやすそうなのですが、USBの形で手に入るものは少ないようです。 linuxwireless.orgの対応表をみてもUSB系でAPモードがONになるドライバは次に挙げるものだけでほとんどないんですよね。

  • Marvell - libertas_tf
  • p54usb - Intersil/Conexant
  • rt2500usb - Ralink

この中でhostapdで対応しそうなのは、p54usbだけだけれど、日本で購入できるUSBスティックの情報は、ほとんどないと…。Supported USB wireless devicesの一覧表には40件以上リストされてるのにな…。

国内でも入手可能そうなのはNetGearのWG111ですが、国内品(WG111-300JPS)のUSBIDが、p54usb.cに書かれているものと違い、rtl818xモジュールにこのID(0846:4260)が書かれています。

無線LAN周りのドライバコードをみるとUSB機器は必ずUSBIDが書かれています。 これで検索すると確認されているものと似ている型番でも、USBIDが異なるものがほとんどのようでした。

AtherosチップなUSBスティックを試してみる

試しに近くの家電量販店でAtherosのSuperGに対応しているUSBポートに刺すAterm WL54GUを買ってみましたが、見事に動きませんでした。

なかを開けてみるとチップはAtheros 2524-AQ1Cで、linuxwireless.orgを調べるとzd1211rwドライバを使うようなのです。 いずれにしてもWL54GUはAPモードが動かないので、hostapdでは使えないですね。

2010/01/18追記:
APモードにはならないのですが、zd1211rwドライバで動く事は確認できたのでUSBIDをzd1211-dev MLに投げました。

Alixが対象なので、USB系が難しいとなると、望みはminiPCIしかありません。 これはこれで面倒な気配がただよいますが、調べてみる事にしました。

とりあえず古いブロードバンドルーターを開けてみた

ここで使っていないcoregaのWLBAR-54GTというブロードバンドルーターの中を開けてみると、XG-601というminiPCIな無線LANモジュールが内蔵されていました。

そこで、ケースを壊してアンテナを一緒に取り外しました。 alixに付けてみたところPrism GTチップを使っているらしく無事に認識されました。

このカードは11b/11gに対応していますが、セキュリティはWEPまでの対応なので実用にはちょっと使えない感じです。iptablesでルールを書いてインターネットに出ていくだけにしても良いけれど、踏み台にされても嫌だしなぁ…。

とりあえずこのカードは実験用に確保して、他に使えそうなminiPCIなカードを探す事にしました。

閑話休題:技適マークがない事に気がついた…

目先を少しずらしてみると、気になるのは外したカードに技術基準適合証明マークがカードについていないところです。 しかし技適の対象に対する総務省への問い合せ結果に寄ればMiniPCIカード+アンテナを一体として扱えば問題なさそうです。まぁ伝聞の伝聞ですけどね。

この解釈は玄人志向からMiniPCI+アンテナが販売されている事から考えても、合理的なところだと思います。 MiniPCIカードに印加される電圧は一定ですし、alixは金属ケースに入れるので関係ないですが、元々プラスチックケースに入っていたところからもカードやアンテナケーブルからの副次的な電波も問題はなさそうです。

ま、WLBAR-54GT本体に貼り付けてあるシールに技適の証明番号は印字されてないんですけどね。たしかシールが本体に付属していたような気がかすかにする…。

いずれにしても、新しいカードがみつかるまでは、取り外したXG-601なカードとアンテナを使う事に問題はなさそうです。

新しいminiPCIカードを探すための、今後の方針について

さて、探せそうなのは次のような手段でしょうか。

  • 国内販売品からminiPCIカードとアンテナをそのまま取り外す
  • 国内販売品の保守部品からminiPCIカードとアンテナを一体で入手
  • 玄人志向の802.11ND-MPCIを購入
案1:国内販売品からカードとアンテナを取り外す

miniPCIカードについて、まとめているサイトをみると、WN-G54/BBRや、WN-AG/BBRを分解すればatherosのカードが手に入るようです。 また無印のWN-G54のコントローラーににヒートシンクをつける記事によれば、こちらにもAtheros製のminiPCIカードが付いているようです。

いつの間にか壊れていたアクセスポイントによればMN-WAP54gはatheros系のminiPCIなカードを内蔵しているもよう。

XG-600なカードがついている情報は、いくつかあるけれど、それは手持ちのXG-601同様にWEPまでしか対応していないみたいなので、候補からは外しました。

案2:保守部品からカードとアンテナを調達する

メーカーの保守用部品でアンテナまで販売しているのは、AirPort Extreme用の保守部品ぐらいしかみつけられませんでした。

案3:玄人志向のminiPCIカード+アンテナを購入

Buffaloの無線ブロードバンドルーターには、この玄人志向と同じWLI-MPCI-G54を搭載しているようです。玄人志向からカードを入手するのは安全でお手軽ですが、お勧めする人はいても具体的な成功例がみつかりませんでした。

たぶんb43系で使えるんだろうけれど、値段は安くはないし、試そうにもちょっとなぁ…。

どれもいまいちですね。 しばらくはリサイクルショップを周って、古いブロードバンドルーターを漁ってみようと思います。あまり廉価なものはminiPCIカードを持たずに組み込まれている場合があるから、なかなか難しそうですが…。

2010/01/15

AlixのUbuntu 9.10を無線LANクライアントにする

AlixにUbuntu 9.10をインストールしたのは、無線LANのAccess Point (AP)を作成するはずだったのですが、Ubuntuのインストールに集中してしまいすっかり忘れていました。 そこでとりあえず普通にクライアントとして、無線LANに接続する事にしました。

実際のところUbuntu 9.10のインストールが一番面倒で、それが終れば/etc/network/interfacesファイルだけで無線LANに接続する方法は、HOWTO: Wireless Security - WPA1, WPA2, LEAP, etc.に詳しく説明されています。

通常であればデスクトップ環境+無線LANと思われるので、普通のマニュアルのようにNetworkManagerからGUIで設定をするのがお勧めです。

今回はカーネルのコンパイルはせず、(Windows XP/2000用)NDISドライバを使用しない前提で進めようと思います。

家の無線LAN環境

以前はブロードバンドルーターとして使っていたCoregaのCG-WLRGNXを無線LANのAP(親機)として使用しています。

  • ステルスAPを有効にしてESSIDは非公開 (後で解除)
  • WPA/WPA2-PSKを有効
  • WEPは無効

LogitecとPlanexの無線LANクライアントを試してみる

手持ちのLogitec LAN-W150N/U2 SeriesPlanex GW-USMicroNを素のUbuntu 9.10 linux-image-genericカーネルが稼働するalixに接続してみました。

Planex GW-USMicroNを試す

とりあえず使えている方から…。

何もせずに動くけれども…

何も考えずにUSBコネクタに差すと、ra0がデバイス名として認識されます。 参考にしたサイトのように/etc/network/interfacesファイルを編集しましたが、 電源を入れてからコネクションが確立するまでの時間が不定期で、また接続後も切れ易く実用できない感じでした。

RT2870STA.datファイルの準備

syslogをみる限りどうやらいくつか問題があるようで、その中でも/etc/Wireless/RT2870STA/RT2870STA.datファイルがないというメッセージが目につきます。 これが必要なのかどうか判断が付かなかったので入手してみました。 古いURLはいろいろ見付かったのですが、現在はralink.comのlinuxサポートページからGPLなドライバが入手できます。

ダウンロードしてきたファイルは、RT2870_LinuxSTA_V2.3.0.0.tar.tar.bz2です。 この中にRT2870STA.datファイルの雛型があったので、メッセージにある場所にコピーして修正しました。 チャネルが1-13しかないのに、1-14まで使うのが初期設定だったりするようなので、状況に合せて調整すれば接続までの余計な手間が省けそうなので使う事にしました。

使っているCoregaの無線LANの親機はWPA2をしゃべるはずなのに認証にTKIPを要求するなど、そんなものかもしれませんが、参考にしたサイトのままではネゴシエーションがうまく行かないことがわかりました。

そこで次のような設定にしています。

/etc/Wireless/RT2870STA/RT2870STA.datファイル

#The word of "Default" must not be removed
Default
CountryRegion=1
CountryRegionABand=7
CountryCode=JP
ChannelGeography=2
SSID=xxxxxxxxxxxx
NetworkType=Infra
WirelessMode=6
Channel=11
BeaconPeriod=100
TxPower=100
BGProtection=0
TxPreamble=0
RTSThreshold=2347
FragThreshold=2346
TxBurst=1
PktAggregate=0
WmmCapable=1
AckPolicy=0;0;0;0
AuthMode=WPA2
EncrypType=
WPAPSK=
DefaultKeyID=1
Key1Type=0
Key1Str=
Key2Type=0
Key2Str=
Key3Type=0
Key3Str=
Key4Type=0
Key4Str=
PSMode=CAM
AutoRoaming=0
RoamThreshold=70
APSDCapable=0
APSDAC=0;0;0;0
HT_RDG=1
HT_EXTCHA=0
HT_OpMode=0
HT_MpduDensity=4
HT_BW=0
HT_BADecline=0
HT_AutoBA=1
HT_AMSDU=0
HT_BAWinSize=64
HT_GI=1
HT_MCS=33
HT_MIMOPSMode=3
HT_DisallowTKIP=1
IEEE80211H=0
TGnWifiTest=0
WirelessEvent=0
CarrierDetect=0
AntDiversity=0
BeaconLostTime=4
PSP_XLINK_MODE=0

/etc/network/interfacesファイルのra0設定の抜粋

auto ra0
iface ra0 inet static
  address 192.168.1.4
  netmask 255.255.255.0
  gateway 192.168.1.1
  wpa-driver wext
  wpa-ssid xxxxxxxxxxxx
  wpa-ap-scan 2
  wpa-proto RSN WPA
  wpa-pairwise CCMP TKIP
  wpa-group CCMP TKIP
  wpa-key-mgmt WPA-PSK
  wpa-psk xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

interfacesファイルではwpa-ap-scan 2を使っていますが、CoregaのステルスAP機能を有効にした状態では接続ができませんでした。 どうせステルスAP機能は気休めなので、この部分は諦めて設定をステルスAP機能を無効にしました。

Logitec LAN-W150N/U2 Seriesを試す

入手は容易だけど、動かない

近所の家電量販店をみると、複数の店舗で確認する事ができました。 田舎に住んでいると入手が容易な事は大切なことです。

しかし結論から書くと、うまく動かす事ができていません。

現状について

普通にalixのUSBコネクタに接続すると、wlan0がデバイス名として認識されます。

Ubuntu日本語フォーラム内のPLANEXのUSB無線LAN子機がubuntu9.10で使えずお困りの方への中で、rt2800usb.ko等をblacklistに登録する方法があります。 これと同じ対応をするとra0デバイスとして認識されますが、今のところネットワークには繋がっていません。

まとめ

動かないものもありましたが、NDISWrapperを使う可能性が残されている事や、今回はalixという少し特殊なハードウェアでの結果だという事は強調しておきたいと思います。

2010/01/14

Ubuntu 8.04 Hardyと9.10 KarmicでのttyS0の扱い方

AlixでUbuntu 8.04から9.10へアップグレードした時に、upstart-compat-sysvとupstartでの書式の違いからttyS0が認識されないという事態に陥りました。

Ubuntu 8.04でのttyS0の認識方法

8.04ではgettyが/etc/event.d/ディレクトリ以下のファイルで制御されています。 Ubuntu Forumなどで調べると次のような手順がいくつかみつかり、ttyS0ファイルを作成してシリアル経由でアクセスできました。

$ cd /etc/event.d
$ sudo rm tty?
$ sudo vi ttyS0

/etc/event.d/ttyS0ファイル

# ttyS0 - getty
#
start on stopped rc2
start on stopped rc3
start on stopped rc4
start on stopped rc5

stop on runlevel 0
stop on runlevel 1
stop on runlevel 6

respawn
exec /sbin/getty -L 38400 ttyS0 vt100
9.10へアップグレードした際の問題点

まとめると次のようなポイントで問題になります。

  • getty起動用スクリプトの配置場所の変更
  • 複数のstart行を受け付けない書式の変更
  • "start on stopped"に続く書式の変更

まずgettyを起動するスクリプトの配置場所が、9.10では/etc/initディレクトリ以下に変更されています。

単純にファイルを/etc/event.dから/etc/initに移せば良いかというと、そうではないようです。 いろいろ試してみるとスクリプト内に複数のstart行がある事で問題になることがわかります。

また他のファイルをみると、start on stoppedに続く書式が、rc2からrc RUNLEVEL=2のように変更されている事がわかります。

両バージョンへの対応

せめてファイルを移動するだけで済むように、 Ubuntu 8.04と9.10に対応するスクリプトの書き方を考えてみます。

問題となっているのが複数のstart行なので、これを1行にまとめます。

続いてstart on stoppedをやめることにしました。 これだと/etc/rc2.d/のスクリプトが起動している最中に端末が上がってしまいますが、 多少画面がみずらくなるぐらいで許容範囲と判断しました。

Ubunt 8.04での新しい/etc/event.d/ttyS0.conf

start on runlevel [2345]
stop on runlevel [!2345]
respawn
exec /sbin/getty -L 38400 ttyS0 vt100

これで問題なく動くので、9.10ではこれを/etc/initディレクトリに移動する事にします。

$ lsb_release -r
Release:	9.10
$ mv /etc/event.d/ttyS0 /etc/init/ttyS0.conf

9.10にした後ではgettyが起動しないためシリアル経由で作業ができない事になりますが、grubからrecovery modeを選択する事でシリアルから起動する事ができます。 またCFカードを抜いて別マシンで作業する方法や、SSH経由でログインするなどして作業を行ないます。

さいごに

Ubuntu 8.04 LTSぐらいまでのよくあるttyS0の有効化の方法では、複数のstart行を記述しています。

まぁalixみたいにtty端末のないマシンでUbuntuを使うのはレアケースかもしれませんが、 Ubuntu 10.04 LTSがリリースされたらサーバー版の更新作業で多少の混乱が起るような気がします。

もし自動でマイグレーションするようpostinstスクリプトを書くなら、start, stop行は決めうちのテンプレートを準備して、respawnexecで始まる行だけ後ろにコピーすれば何とかなるかなぁ…。

2010/01/12

Ubuntu 8.04上でAlix用にUbuntu 9.10 (Karmic)なCFカードを作成する

無線LANのクライアント、うまく行けばAPにできないかと思い、手持ちのLogitec LAN-W150N/U2 SeriesPlanex GW-USMicroNを動かそうとしたのですが、いつも使っているDebian lennyではカーネルを再構築する以外の方法がなさそうだったのでUbuntu 9.10 (Karmic)をalixに導入する事にしました。

ちなみにKarmic上で各デバイスがロードするドライバは次の通りで、これはlenny用のfirmware-ralinkパッケージには含まれていません。

  • LAN-W150N/U2 Series: rt2800usb (firmware: rt2870.bin)
  • GW-USMicroN: rt2870sta (firmware: rt2870.bin)

今回の作業はCFカードの設定までですが、これはUbuntu 8.04 (hardy)上で行ない、CFカードは/dev/sdgとして認識されている前提で説明をしています。

debootstrapからのkarmic導入はうまくいかない

karmicを直接導入するには、以下のコマンドで行えますが、kernel-imageを導入する段階でgrubの導入が先に進んでしまい、うまく導入する事ができません。 しかしkermit上で作業を進めれば、問題なく進める事ができるかもしれません。

$ sudo debootstrap --arch i386 karmic /mnt/cf http://jp.archive.ubuntu.com/ubuntu /usr/share/debootstrap/scripts/gutsy

今回は8.04経由なので少し冗長な説明になっていますが、良い機会なので昔に書いたドキュメントを更新するつもりでまとめ直しました。 まぁ強制的にlinux-imageパッケージだけ展開すれば良さそうなものですけどね。

CFカードへのUbuntu 8.04 Hardyの導入

いつもと同じ準備作業

ubuntu 8.04 (hardy)をセットアップし、後からアップグレードします。 まずは以前と同じ手順で始めます。

$ sudo /sbin/fdisk /dev/sdg
$ sudo /sbin/mke2fs /dev/sdg1
$ sudo /sbin/tune2fs -c 0 -i 0 /dev/sdg1
$ sudo mount /dev/sdg1 /mnt/cf
$ sudo debootstrap --arch i386 hardy /mnt/cf

続いて手順に従ってgrubの導入を行ないます。

$ sudo grub-install --root-directory=/mnt/cf /dev/sdg
grub周りの設定

/boot以下にlinuxのカーネルイメージがないので、最低限必要なものだけ追加します。 Ubuntuでは"linux-image-server"はPAEに対応していないアーキテクチャでは起動できないので、linux-image-genericを選択する必要があります。

apt-getを使うためにchrootコマンドを使います。 そしてカーネルパッケージを導入する前にsources.listファイルを編集します。 既存の1行を削除して、下記の内容で上書きしてしまいます。

$ sudo chroot /mnt/cf /bin/bash
# vi /etc/apt/sources.list

/etc/apt/sources.listファイル

deb http://jp.archive.ubuntu.com/ubuntu/ hardy main restricted
deb-src http://jp.archive.ubuntu.com/ubuntu/ hardy main restricted

deb http://jp.archive.ubuntu.com/ubuntu/ hardy-updates main restricted
deb-src http://jp.archive.ubuntu.com/ubuntu/ hardy-updates main restricted

deb http://security.ubuntu.com/ubuntu hardy-security main restricted
deb-src http://security.ubuntu.com/ubuntu hardy-security main restricted

apt-get updateはパッケージの署名関連の情報を更新するために行なっています。

# apt-get update
# apt-get install linux-image-generic

grubが使うmenu.lstファイルを作成する時には、lennyとは異なり/dev/sda1を指定します。

/boot/grub/menu.lstファイル

serial --speed=38400
terminal serial
##
default         0
timeout         10
##
title           Ubuntu 8.04
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.24-26-generic root=/dev/sda1 console=ttyS0,38400n8
initrd          /boot/initrd.img-2.6.24-26-generic
savedefault
シリアル端末周りの設定

Ubuntuでは/etc/inittabがないので、/etc/event.d/ディレクトリの不要なtty?なファイルを削除し、ttyS0ファイルを作成します。

$ cd /etc/event.d
$ sudo rm tty?
$ sudo vi ttyS0

/etc/event.d/ttyS0ファイルの内容

start on runlevel [2345]
stop on runlevel [!2345]
respawn
exec /sbin/getty -L 38400 ttyS0 vt100
その他、fstab周り

/etc/fstabを編集します。 UbuntuではHDDも/dev/sd*として認識されるので、/dev/sda1を使います。

/etc/fstabファイル

/dev/sda1 / ext3 defaults,relatime 0 0
proc /proc proc defaults 0 0

ここまでで、最低限の設定が完了しました。 引き続きalixにCFカードを入れてKarmicにアップグレードする準備をします。 umountコマンドを使わずにCFカードを抜いてしまうと、CFカードに書き込まれずにバッファに溜っているデータが消えてしまう可能性があるので、ちゃんと終了処理を行なうようにします。

$ sudo umount /mnt/cf

シリアル経由でのAlix上での作業を開始

ネットワーク周りの設定

まだ中途半端なシステムを稼働させるために必要な設定をいれていきます。 ネットワーク周りの設定は環境によるので適宜変更してください。

/etc/network/interfacesファイルの設定

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

設定が終れば、NICを起動します。

# ifup lo
# ifup eth0

リモートから作業をするためにsshdを起動してsudoを設定します。

# apt-get install openssh-server
# visudo

visudoによるsudo設定の変更

...
%sudo ALL=NOPASSWD: ALL
...

SSH経由でログインして作業をするためのID(user01)を作成します。

# useradd -m -G sudo user01
# passwd user01

ネットワーク経由で作業を継続

引き続いてgrub周りの設定を再び

無事にネットワークに接続できれば、作成したIDでログインし、grub周りの設定を行ないます。

$ sudo apt-get install grub
$ sudo update-grub

update-grubの実行中にmenu.lstを置き換えるか尋ねられるためinstall_newを選択し、新しいファイルをインストールします。 しかしこのままでは使えないので、先頭に既存のものも残りますが、編集をします。

/etc/grub/menu.lstファイルの変更部分抜粋


...
# kopt=/dev/sda1 console=ttyS0,38400n8
...
# defoptions=
...

新しいlinux-imageが導入された時にmenu.lstファイルを更新するように、 kernel-img.confファイルに設定を追加します。

/etc/kernel-img.confファイルの内容

# Kernel Image management overrides
# See kernel-img.conf(5) for details
do_symlinks = Yes
do_bootloader = no
do_initrd = yes
postinst_hook = update-grub
postrm_hook   = update-grub

最後にupdate-grubコマンドを実行し、menu.lstファイルを生成します。

$ sudo update-grub

menu.lstファイルにシリアル関連の情報が追加されることを確認する

...
root		(hd0,0)
kernel		/boot/vmlinuz-2.6.24-16-generic /dev/sda1 ro console=ttyS0,38400n8 quiet splash
initrd		/boot/initrd.img-2.6.24-16-generic
...

# kopt=で指定した内容を/boot/grub/menu.lstファイルが含んでいる事を確認します。 ここまでで問題なければdefault 0で指定されているファイル先頭を飛して、update-grubで作成されたエントリからブートするように変更しておきます。

変更後のmenu.lstファイル

...
default         1
...
カーネルを含むパッケージの更新

ここまで終ればhardyのまま、パッケージを最新にします。

$ sudo apt-get dist-upgrade

新しいlinux-imageとlibc6を反映させるためにシステムを再起動します。

$ sudo reboot
いよいよkarmicへのアップグレード

コマンドラインからのUbuntuのアップグレード手順は、Network Upgrade for Ubuntu Servers (Recommended)にあります。

Ubuntu 8.04がベースなのでdo-release-upgradeコマンドには-dオプションを使います。

$ sudo apt-get install update-manager-core
$ sudo do-release-upgrade -d

アップグレード対象パッケージの選定と、ダウンロードを始めるタイミングで確認のプロンプトが表れます。 そこで質問の度に停止するので放っておく事はできませんが、yを入力しているとkarmicへのバージョンアップが完了するはずです。

Karmicにアップグレードした後の作業

do-release-upgradeによって再起動が行なわれたとして、必要になる残作業を書いていきます。

ttyS0を認識させる方法

upstart-compat-sysvの仕組みがupstartによって置き換えられたのにもかかわらず、/etc/event.d/ttyS0ファイルがそのままになっているため、gettyが起動せずシリアル経由で接続してもログインプロンプトが表れません。

CFカードを別マシンでマウントして編集しても良いのですが、alix上で作業するなら、SSH経由のネットワークログインか、grubのメニューでrecovery modeを選択してログインします。

8.04では互換性のないttyS0ファイルを作成する事もできるので、独自に作成している場合はマニュアルに当るなどしてください。 このブログでも、Ubuntu 8.04 Hardyと9.10 KarmicでのttyS0の扱い方で簡単な説明をしています。

今回は8.04で互換性のある書式で作成したので、単純にmvします。

$ sudo mv /etc/event.d/ttyS0 /etc/init/ttyS0.conf

実際に使うための便利な設定

manコマンドの追加

マニュアルはパッケージによってインストールされていますが、それを見るために必要なmanが入っていません。

$ sudo apt-get install man-db
ホスト名の変更

CFカードを操作したホスト名がそのまま/etc/hostnameに入っているはずです。 設定されている名前を変更すれば、次の起動時にその名前になります。

ただしsudoを一緒に使うのであれば、IPアドレスを引けるように新しい名前を反映させる前に/etc/hostsを編集します。 例えば、ubuntuにホスト名を変更するとします。

$ sudo vi /etc/hosts

/etc/hostsファイルの内容

127.0.0.1 localhost ubuntu
::1 localhost ubuntu

もし再起動なしにホスト名の変更をしたいのであれば、hostnameコマンドを使います。

$ sudo hostname ubuntu

普通は間違ってrootで実行すると危険なので、ホスト名を確認するためにhostnameコマンドは使いません。 unameコマンドを使いましょう。

$ uname -n
ntpdの設定

ローカルにあるntpサーバーをみるようにntpdateの設定を変更します。 Debianとは違いntpdate自体は既に導入されているはずです。

/etc/default/ntpdateファイル

...
NTPDATE_USE_NTP_CONF=no
...
NTPSERVERS="192.168.1.2 ntp.ring.gr.jp ntp.ubuntu.com"
...  

もし長時間稼働させたままのサーバーにするのであれば、稼働中も時刻を修正するようにntpパッケージを導入します。

$ sudo apt-get install ntp

ntpd.confファイルを編集します。

/etc/openntpd/ntpd.conf

...
#server ntp.ubuntu.com
server 192.168.1.2
...
locale (ja_JP.UTF-8)の設定

このままでは日本語を表示させたいl場面で混乱するので、localeの設定を行ないます。

$ sudo locale-gen ja_JP.UTF-8
$ sudo locale-gen C

端末で$ locale -aコマンドを実行して、ja_JP.utf8が表示されれば完了です。

日付表示をJSTに変更する

現段階ではdateコマンドなどで表示される時刻がUTCになっているので、 日本標準時(JST)に変更しておきます。

$ cd /etc
$ sudo rm localtime
$ sudo ln -s /usr/share/zoneinfo/Japan localtime

さいごに

ここまでで必要な作業はだいたい完了したので、無線LANを試すところは次の機会にしようと思います。

今回の作業で気がついたのですが、alixはAMD Geode LXなので686なマシンタイプ用のカーネルで動くんですよね。 ブロードバンドルーターにしているalixもlinux-image-686に変更しておかないと。

まぁここまで頑張っても、ここから先に何をするかが問題ですからね…。 とりあえずやり直しが効くようにCFカードをデスクトップに持ってきてバックアップをddコマンドで取っておきましょう。

$ sudo dd if=/dev/sdg of=alix_ubuntu_cfcard.img bs=512

2010/01/10

献血をする理由

今日は会津若松市で恒例になっている十日市という市というよりもメジャーなお祭の日だったので、さらっと見物にいってきました。 そこで市役所の前で献血をして帰ってきたのですが、ふと帰る道すがら献血をしようと思った時の事を思い出していました。

献血するまで…

最初に献血を意識したのは15年以上前、高校一年の文化祭の時に、生徒用玄関の前に献血車が止まっていた時の事だと思います。 でも、当時から気弱だった高校生の私は、「困っている人がいます」という大義名分を後ろめたくも感じながらも、なんとなく怖くて、なにより面倒な事と思って避けていました。

いまから思えば200mL献血しか出来なかったはずだから、 それほど役には立たなかったかもしれないけれど、そんな事も言い訳にしかならないか。

400mL献血と比較すると、200mLは使用時に混ぜる血液の数が増えるので、 患者のリスクが増える点、医療機関で手間がかかり使いずらいという意見がある点、などが報道されています。

不定期ですが継続して献血をする理由は、手術なんかで輸血をすると献血ができなくなるから。 将来必要になった時のために預けているような感覚です。まぁ自己満足である事は間違いないでしょう。

とはいえ、最初に献血した経緯なんか覚えていない

最初の献血は大学生の時で「二十歳の献血♪」とか、それぐらいの気持ちだったと思います。 それに高校時代よりは、面倒なことも少しづつしながら前向きに生きてたし。

とはいえ、高校の時に母親が入院して点滴のように輸血をした後、「身体が楽になる」と話していた事も影響していたのかもしれません。

入院した時点で母が末期の癌だった事は知っていたし、薄情かもしれないけれど血液を贅沢に使っているなぁというのが当時の正直な感想でした。 ひょっとすると、その時に感じた後ろめたいような、申し分けないような気持ちが、献血をしようとする今の自分の土台にあるのかもしれません。

輸血といえば手術で失った血液を補充するぐらいしか使い道を知らなかったし、いろいろ使い道はあるんだという事をその時に知りました。

20代の献血者数が減っているというけれど

いまどき単純な「助け合い」なんていう言葉だけで増えるわけないと思うんですよね。 いや、きっと昔だってそんな理由で献血する人が多かったわけじゃないだろうにと思います。

きっとそれは漠然とした「やらなきゃ」っていう気持ちだったんじゃないかな。 けれどそれは「助け合いましょう」なんていう言葉で生まれるものではないと思います。

基本かもしれないけれど、血液をどういう人が必要としているのか、「輸血されたら献血してやろう」という考え方が通用しない事を伝えるべきなんだと思います。

必要な情報を知った上で、個々人が判断すればいいことですが、「輸血されたら〜」な人がそれなりに居るような気がしてなりません。

献血事業を掌握するのは厚生労働省

嫌な話しだけれど厚労省の担当者は普及活動が下手だと思う。 400mL献血が重要な理由を説明するなんていう事は、二の次のはず。 まずは献血の必要性を基本から訴えてほしい。

まさか献血の必要性を一切、訴えない萌えキャラサイトを作って済むとか思ってんじゃないですよね…。 幼稚園児に献血の方法を教えたいのか、これでボランティアを増やすつもりじゃないよね、とか小一時間ほど話しがしたい内容になっています。

効果的な啓蒙活動の方法についてコナミかSCEの広報にでも相談すればいいんじゃないのかなぁ。

けれど頂いたナースキティ&けんけつちゃんの手帳は、机の上で使っていこうと思います。 こういうノベルティは良いと思うんだけどさ。

基本的な事は説明しなくてもわかるでしょ、といった基礎を固めずに家を作るような行為の積み重ねが今の惨状を招いているんだと思います。

AlixでDebian lennyにTrac環境を構築してみた

alix上にDebian lennyをインストールした環境に、 subversionとバグトラッキングシステム(BTS)のTracを導入してみました。

Lennyの導入

このブログの記事: Lennyをインストールしてみるdebianをsubversionサーバーにするに、おおまかな方法を掲載しています。 CFカードにDebian環境を作るところは、情報が分散しているから改めてまとめないとだなぁ。

この記事ではLennyがalix上で動作しているところから始めてtracを導入してみます。

tracパッケージの導入

$ sudo apt-get install trac libapache2-mod-python

関連するパッケージがどこに配置されているかは、dpkg -L tracで調べることができます。

trac関連のセットアップ

trac用のファイルはどこに配置するのか、明確に決まったところはありません。 パッケージの管理下にないファイルは、環境に合せて適宜変換してください。

専用ディレクトリの準備

自分のアプリケーション専用ディレクトリとして、"/app"を準備しています。 この下に"trac"用のディレクトリを作成する事にしました。

$ sudo mkdir -p /app/trac/projects
$ sudo mkdir /app/trac/.egg-cache
$ sudo chown www-data:www-data /app/trac/.egg-cache /app/trac/projects

tracではapacheのBASIC認証で渡されたユーザーIDをtracの利用者IDとして受け入れます。 "admin"を管理者用IDとして、"user01"を一般ユーザーとして準備しておきます。

$ sudo touch /app/trac/.htpasswd
$ sudo htpasswd /app/trac/.htpasswd admin
$ sudo htpasswd /app/trac/.htpasswd user01
$ sudo chgrp www-data /app/trac/.htpasswd
$ sudo chown 640 /app/trac/.htpasswd

そういえば例としてhtpasswdを使う時は、だいたい新規に1つのIDを登録するので -c オプションを一緒に書くのではないでしょうか。 もちろん、それまでのファイルの内容は消えてしまうので、 -c オプションは本番環境では使い物になりません。 バックアップを常に取る習慣をつけることと、そういう危険な作業から身を遠ざけるスキルを身につけたいものです。

apache関連の設定
$ cd /etc/apache2/sites-available
$ sudo vi trac

"trac"ファイルは以下のような内容にします。 今回はサーバーのIPアドレスを"192.168.10.10"にしているので、先頭2行に書かれたIPを環境に合せて変更してください。

/etc/apache2/sites-available/tracの内容

<VirtualHost 192.168.10.10:80>
  ServerName 192.168.10.10
  DocumentRoot /var/www
  <Directory "/var/www">
    SetHandler    None
    Options All
    Order deny,allow
    Deny from none
    Allow from all
  </Directory>

  <Location /trac>
    SetHandler    mod_python
    PythonHandler trac.web.modpython_frontend
    PythonOption  TracEnvParentDir /app/trac/projects
    PythonOption  TracUriRoot      /trac
    PythonOption  PYTHON_EGG_CACHE /app/trac/.egg-cache
  </Location>
 
  <locationMatch "/trac/[[:alnum:]]+/login">
    AuthType Basic
    AuthName "trac"
    AuthUserFile /app/trac/.htpasswd
    Require valid-user
  </locationMatch>

  ErrorLog /var/log/apache2/error.log
  LogLevel warn
  CustomLog /var/log/apache2/access.log combined
  ServerSignature On

</VirtualHost>

最後にapacheで設定を有効にするために、"site-enabled"に反映させます。

$ sudo /usr/sbin/a2ensite trac
設定の確認方法

apacheをリスタートして、実際にアクセスしてみます。

$ sudo /etc/init.d/apache2 restart

続いてブラウザを使ってアクセスしてみます。 まだプロジェクトの設定をしていないので、タイトルだけが表示されます。

http://192.168.10.10/trac/へのアクセス結果

Available Projects

とりあえず使うまでの手続き

Tracは基本的にプロジェクト毎に設定が必要で、複数のプロジェクトを便利に管理する方法はないようです。 そのためプロジェクトを作成してから、ユーザー権限やプラグインの設定が必要になります。

Tracプロジェクトの作成

稼働確認をするための"testproj01"を作成します。

$ sudo -u www-data trac-admin /app/trac/projects/testproj01 initenv

trac-admin実行結果

Creating a new Trac environment at /app/trac/projects/testproj01
...
Project Name [My Project]> Test Projects
...
Database connection string [sqlite:db/trac.db]> 
...
Repository type [svn]> 
...
Path to repository [/path/to/repos]> /var/lib/svn/testproj01
...
Congratulations!
SVNリポジトリの準備

svnのリポジトリの場所は実際に存在する場所にしてください。 もしまだ準備していなければ適当な場所にcdしてから、次のコマンドでディレクトリを準備します。

$ sudo svnadmin create testproj01
テストプロジェクトを使った確認

Webブラウザを開いて、 先ほどと同じようにアクセスしてみます。

先ほどは表われなかったプロジェクト名が表示されれば、成功です。

ユーザー権限の修正

現時点でのユーザー権限を確認しておきます。

$ sudo -u www-data trac-admin /app/trac/projects/testproj01
Trac [/app/trac/projects/testproj01]> permission list
User           Action         
------------------------------
anonymous      BROWSER_VIEW   
anonymous      CHANGESET_VIEW 
anonymous      FILE_VIEW      
anonymous      LOG_VIEW       
anonymous      MILESTONE_VIEW 
anonymous      REPORT_SQL_VIEW
anonymous      REPORT_VIEW    
anonymous      ROADMAP_VIEW   
anonymous      SEARCH_VIEW    
anonymous      TICKET_VIEW    
anonymous      TIMELINE_VIEW  
anonymous      WIKI_VIEW      
authenticated  TICKET_CREATE  
authenticated  TICKET_MODIFY  
authenticated  WIKI_CREATE    
authenticated  WIKI_MODIFY 

今回はあらかじめ"admin"と"user01"のユーザーIDを作成していますので、 "admin"には管理者権限を追加します。user01はそのままにして、"authenticated"ユーザーの権限で動かします。

Trac [/app/trac/projects/testproj01]> permission add admin TRAC_ADMIN

これで"admin"ユーザーでログインすると、 Admin タブが表示され選択可能になります。 この後はプラグインを加えていきます。

プラグインの追加方法

あると便利なプラグインがいくつかありますが、今回のようにパッケージでTracを導入している場合は、 導入先が問題になりそうです。そういう事を考えないのが普通そうですけどね。

"easy_install"を使って本来はパッケージで管理されているシステムディレクトリに導入するのは、 少し嫌だったので別ディレクトリに導入するようにしてみました。 このために設定の追加が必要になります。

この別ディレクトリとして /app/trac/lib を作成します。

$ sudo mkdir /app/trac/lib/lib/python2.5/site-packages

今回はちょっとだけ手数の多い MasterTicketsPlugin を導入してみます。 マニュアルは配布元の tracHacks::MasterTicketsPluginにあります。

まずはgraphvizを追加で導入します。

$ sudo apt-get install graphviz

配布元からパッケージをダウンロードして、サーバー上で展開します。

$ unzip masterticketsplugin-r7356.zip
$ cd masterticketsplugin/0.11
$ chmod -R a+rX .
$ python setup.py bdist_egg
$ cd dist
$ sudo env PYTHONPATH=/app/trac/lib/lib/python2.5/site-packages easy_install --prefix=/app/trac/lib TracMasterTickets-2.1.3-py2.5.egg

easy_installの実行結果

Creating /app/trac/lib/lib/python2.5/site-packages/site.py
Processing TracMasterTickets-2.1.3-py2.5.egg
Copying TracMasterTickets-2.1.3-py2.5.egg to /app/trac/lib/lib/python2.5/site-packages
Adding TracMasterTickets 2.1.3 to easy-install.pth file

Installed /app/trac/lib/lib/python2.5/site-packages/TracMasterTickets-2.1.3-py2.5.egg
Processing dependencies for TracMasterTickets==2.1.3
Finished processing dependencies for TracMasterTickets==2.1.3

このままでは mod_python が必要なパッケージを見つけられないので、 apacheの envvarsPYTHONPATH を追加してライブラリを探す時のパスに追加します。

/etc/apache2/envvarsの編集

...
export PYTHONPATH=/app/trac/lib/lib/python2.5/site-packages

trac.ini ファイルを編集して必要な設定をファイルの最後に追加します。

$ sudo vi /app/trac/projects/testproj01/conf/trac.ini
[components]
mastertickets.* = enabled

[ticket-custom]
blocking = text
blocking.label = Blocking
blockedby = text
blockedby.label = Blocked By

最後に upgrade しておきます。

$ sudo env PYTHONPATH=/app/trac/lib/lib/python2.5/site-packages trac-admin /app/trac/projects/testproj01 upgrade

これで mod_python から導入したパッケージが認識できるはずです。 ここまでの設定が終ってからapacheのプロセスをリスタートします。

$ sudo /etc/init.d/apache2 restart

再び admin ユーザーでログインしてから、AdminタブのPluginsを開くと TracMasterTickets のセクションが表われます。

また新規のチケットを開く時にBlocking, Blocked Byを入力するフィールドが追加されているため、ここに数字を入れて親子関係を定義する事ができるようになります。

うまく動かないときのデバッグ方法

apacheの設定ファイルの中で、ErrorLogで指定した場所にエラーログが出力されます。 VirtualHostを再定義しているため、/etc/apache2/sites-enabled/000-defaultは無視されます。 Log関連以外で必要な設定があれば、コピーしておきましょう。

Tracレベルのエラーメッセージは"Admin"タブの"Logging"セクションで設定します。 確認のためには DEBUG レベルのメッセージを出力すると良いと思いますが、 本番環境では WARNING 以上に設定するなどログサイズに気をつけましょう。

syslogにログを出力すれば、/etc/syslogd.conf or /etc/rsyslog.confの設定によりますが、基本的には/var/log以下のファイルに書き込まれます。

まとめ + 今後の展望

今回はTrancendの2GB x266なCFカードに入れたまっさらなDebian LennyにTracをパッケージから入れてみました。 もしソースからtracを/opt以下などに入れても、envvarsの編集を前倒しで行なうぐらいで動くはずです。

まだsubversionと連携させるための設定が終っていませんが、 これは定型的な作業なので他のサイトに書かれている以上の作業はないと思います。

ただしsubversionのpost-commitをいじるので、スクリプトが正常に動作するまではテスト用のプロジェクトで手順を確立するようにしましょう。

2010/01/03

2010年の書き初め:GraphvizでTracのBasic Workflowを描く

はぁ、あっという間に2000年代も10年が経ってしまいました。 今年もよろしくお願いします。

書き初めという事でドキュメントの図そのままですが、Graphvizを使ってTrac 0.11から標準になったBasic Workflowを描いてみました。

Graphvizで絵を描く

構造的なオブジェクトに対して、単純な表記で描く事ができるGraphvizはいろいろな局面で便利なツールです。

Tracをいろいろ試しているところでWorkflowのカスタマイズは将来的に不回避に思えたので、その時のためにGraphvizを使ってWorkflowの.dotファイルを作成してみました。 Tracのマニュアルそのままの図なので、おもしろくはないですけどね。

trac_workflow.dotファイル

digraph TracWorkFlow {
  node [shape=ellipse fontsize=14 width="0.8" margin=0.1 ]

  init [ label="*" color=black ]
  init -> { init } [label="leave" ]
  new [ color=black ]
  new -> { accepted } [ label="accept" color=green fontcolor=green ]
  new -> { assigned } [ label="reassign" color=blue fontcolor=blue ]
  new -> { closed } [label="resolve" color=red fontcolor=red ]
  assigned [ color=blue ]
  assigned -> { assigned } [label="reassign" color=blue fontcolor=blue ]
  assigned -> { accepted } [label="accept" color=green fontcolor=green ]
  assigned -> { closed } [label="resolve" color=red fontcolor=red ]
  accepted [ color=green ]
  accepted -> { accepted } [label="accept" color=green fontcolor=green ]
  accepted -> { assigned } [label="reassign" color=blue fontcolor=blue ]
  accepted -> { closed } [label="resolve" color=red fontcolor=red ]
  closed [ color=red ]
  closed -> { reopened } [label="reopen" color=purple fontcolor=purple ]
  reopened [ color=purple ]
  reopened -> { closed  } [label="resolve" color=red fontcolor=red ]
  reopened -> { accepted } [label="accept" color=green fontcolor=green ]
  reopened -> { assigned } [label="reassign" color=blue fontcolor=blue ]
}
出力結果

結果は次のようになります。

$ dot -o trac_workflow.gif trac_workflow.dot
$ convert trac_workflow.gif trac_workflow.png

dotコマンドで変換後のPNG画像