hnakamur’s blog

ものすごい勢いで忘れる私のために未整理でもいいからとりあえずメモ

2009-12-26

Windows 7環境でEmacs 23.1をセットアップ

GNU Emacs on Windowsを参考にしました。

ユーザー環境変数HOMEを%HOMEDRIVE%%HOMEPATH%として設定して、~/.emacs.d/init.el (.init.elでは読み込まれないようでした)を以下の内容で作成しました。

;; Don't display start-page
(setq inhibit-startup-message t)

;; Hide menu-bar
(tool-bar-mode -1)

;; Window configuration
(if window-system (progn
  (setq initial-frame-alist '((width . 80) (height . 42) (top . 0) (left .
200)))
))

2009-12-19

UL80AGのリカバリー方法

2組のリカバリーディスク

UL80AGでは初めて使うときにリカバリーのDVDを作成するよう促されます。これで作成したリカバリーディスクと付属のリカバリーディスクでそれぞれリカバリーして違いを調べてみました。

ちなみに、後からリカバリーディスクを作る場合は [スタートメニュー]→[すべてのプログラム]→[ASUS Utility]→[AI Recover Burner] でいけるようです。空のDVDが4枚必要と言われますが実際には3枚ですみました (たぶんMS-Officeプリインストールモデルだと4枚なのでしょう)。

作成したリカバリーディスクを使ってリカバリー

作成したリカバリーディスクで起動するとリカバリーが始まります。メディア交換指示に従って2枚目、3枚目を入れていきます。3枚目が読み終わるとここまでの所要時間が表示されます(約30分でした)。

次に"ASUS Preload Wizard"というダイアログが表示されます。ドロップダウンで[Japanese (日本語)]を選択し[次へ]を押します。

[Recovery WizardはASUS製ノートパソコン専用です。…]の画面が表示されたら[次へ]を押します。

次は「以下のオプションから1つ選択」の画面です。選択肢は以下の3つ。

  • HDDの1つめのパーティションに対して、Windowsリカバリーを実施します。

    既存のパーティションテーブルの1つめのパーティションにWindowsをリカバーします。

  • HDDを新たに1パーティションで管理し、Windowsリカバリーを実施します。

    一旦パーティションを全て削除し、ハードディスク全体をCドライブにしてそこにWindowsをリカバーします。

  • HDDを新たに2パーティションで管理し、Windowsリカバリーを実施します。

    一旦パーティションを全て削除し、ハードディスクの60%をCドライブ、40%をDドライブとしCドライブにWindowsをリカバーします。

なお、実際にはどの選択肢を選んでもFAT32の隠しパーティションが1つ作られてそこにリカバーメディアのイメージが格納されます。上でいう「1つめ」や「全体」はこの隠しパーティションを除いた話です。3つの選択肢について UL80 Series User’s Manual for English Edition(E4873) (ASUSTeK Computer Inc. UL80Agからダウンロードできます) p.15 に説明があります(隠しパーティションについては触れられていません)。

[これによりプリインストールされたアプリケーションを工場出荷時の状態に戻すことができます。…]の画面では[次へ]を押します。

[今すぐリカバリーを実行しますか? 「終了」をクリックし、リカバリーを実行します。]の画面では[終了]を押します。するとリカバリーが始まります。

[Recovery finish. Press OK to shutdown your system.]の画面が表示されたら[OK]を押すと電源が落ちます。

電源スイッチを押して起動すると、Windowsの初回起動時の設定が始まりますので、ユーザー名やパスワードなどを適宜設定します。

一通り設定が終わると、ASUSのCM動画(数十秒程度)が再生されます。

それが終わると、[ウイスルバスター 2010]というダイアログが表示されています。[同意して有効にする]を押すとお試し版が使えるようです。が、私はavast! Home Editionを使うので、[後で有効にする]を押して閉じます。

閉じると[AI Recovery Remind]画面があり[工場出荷時の状態のWindowsのコピーが作成されていません。…]と言われていますが、作成済みなので[Windowsの起動時に表示しない]チェックボックスにチェックをつけて右上の×ボタンを押して閉じます。

付属のリカバリーディスクを使ってリカバリー

付属の3枚のメディア

  • (a) "Windows 7 Recovery Media for Windows 7 Products"
  • (b) "Driver&Utility Ver 1.0"
  • (c) "CyberLink Power2Go 6.0"

でリカバーしてみました。 (もう一枚の"Adobe Reader Ver 8.0"というメディアは不要です。 "Driver&Utility Ver 1.0"にAdobe Reader 9が入っているので。)

  1. (a)で起動して途中でメディア交換指示が出たら(b)を入れます。

    (a)で起動したらパーティション構成をどうするかの3つの選択肢(上記のものと同じ)が提示されます。

  2. 再起動後(b)のSETUPを実行してドライバとユーティリティソフトを入れます。
  3. (c)でPower2Goをインストール。
  4. 1.が終わってから起動する度に[システム準備ツール 3.14]というダイアログが表示されます。  ダイアログの中身はこんな感じ。
    • [システムクリーンアップアクション]ドロップダウン
      • システムのOOBE (Out-of-Box Experience) に入る (←デフォルト選択)
      • システム監査モードに入る
    • [一般化する]チェックボックス
    • [シャットダウン オプション]ドロップダウン
      • シャットダウン
      • 再起動 (←デフォルト選択)
      • 終了

    デフォルト状態で[OK]を押すと、ユーザ名/パスワードなどの初期設定が始まります。

リカバリーディスクを作成した場合と比べると以下の点が違いました。

  • 初回設定後の動画が再生されない。
  • スタートメニューにASUSフォルダがない。

    作成したリカバリーディスクでリカバーした場合はここに"Asus WebStorage"がインストールされていました。ASUS WebStorage からダウンロードしてインストールすれば同じように使えるかもしれません。が、試していないので不明です。

  • ウィルスバスター 2010のお試し版が入らない。

    必要ならウイルスバスター2010 30日無料体験版からダウンロードできます。

  • Adobe Reader 9が英語版になっている。

    日本語版にしたい場合は、英語版をアンインストールしてAdobe - Reader 9から日本語版をダウンロード、インストールします。

他にも違いがあるかもしれませんが、気づいたのは以上です。

ASUS UL80AGを購入しました

UL20Aと悩みましたがUL80AGにしました

当初UL20Aを買おうかと思っていたのですが、Amazonの20%引き47,840円を目の当たりにしながら躊躇してたらあっという間に20%引きが終わってしまいました。他の店で買うか悩んだのですが結局AmazonでUL80AGを買いました。2kgなら持ち運びもできるし、Linuxのインストールとかでは光学ドライブがあるほうが楽だし。あと、BUFFALOの増設メモリ PC2-6400 (DDR2-800) 2GB D2/N800-2G/Eもあわせて買いました。

入っていたパーツのメモ

ハードディスク
Seagate Momentus 5400.6 320G ST9320325AS
メモリ
hynix 2GB 2Rx8 PC2-6400S-666-12
無線LAN
Atheros AR9285

2chによるとRealtek RTL8191SE Wireless LAN 802.11n PCI-E NICの場合もあるらしいです(UL20AかUL80AGかはわかりませんが)。

タッチパッド
ELAN PS/2 Port Smart-Pad

ドライバ/ユーティリティ/マニュアルのダウンロードページ

ASUSTeK Computer Inc. UL80Ag

起動オプション

ESC
ブートメディア選択
F2
BIOSメニュー

詳しくは UL80 Series User's Manual for English Edition 参照。 上記のダウンロードページにあります。

2009-12-14

KVMでシリアルコンソールからCentOS 5.4をインストール

CentOS 5.4のホストにvnc+sshトンネリングで接続してkvmでCentOS 5.4をゲストとしてインストールのように苦労しなくても、シリアルコンソールでインストールする手順がCentOS 5.4でKVMを試してみた。 〜 コンソール編 〜 - 理想未来はどうなった?で紹介されていました。

ただ、--os-variant=virtio26を指定するとinternal error unsupported disk type 'vda'などというエラーが出たのでこれは外しました。というわけで以下のコマンドでインストール。

# virt-install --connect qemu:///system -n vm01 -r 512 --vcpus=1 \
 --disk path=/var/lib/libvirt/images/vm01.img,size=10 \
 --os-type linux --accelerate \
 --network network:default \
 --location='http://ftp.riken.jp/Linux/centos/5.4/os/i386' \
 --extra-args='console=tty0 console=ttyS0,115200n8'

CentOS 5.4のホストにvnc+sshトンネリングで接続してkvmでCentOS 5.4をゲストとしてインストール

HowTos/KVM - CentOS Wikiは古いとのことですが、それなりに参考にしました。

# yum install kvm kmod-kvm qemu virt-manager
# groupadd kvm
# usermod -G kvm -a yourusername

ここで一旦リブート。

# reboot

再起動後以下のようにしてインストーラを実行。-cursesオプションは使えないようなので-vncオプションを使ってVNCを使います。

# qemu-img create -f qcow2 vm1.img 10G
# wget http://ftp.riken.jp/Linux/centos/5.4/isos/i386/CentOS-5.4-i386-netinstall.iso
# qemu-kvm -hda vm1.img -cdrom CentOS-5.4-i386-netinstall.iso -m 512 -boot d -vnc :1

私はMacBookからリモートのホストOSにsshでつないで作業していたので、JollysFastVNCというソフトを使い、"Security Type"を"SSH"にして、"SSH Options"を"-L 5901:localhost:5901 yourremotehostname"のように設定してSSHトンネリングで接続しました。なお、JollysFastVNCはalpha版のせいか表示が更新されないことがよくあるので、TABなどを押すか、一旦ウィンドウを閉じて繋ぎ直したりしてしのぎます。

VNCでつながったら、Linuxのブート画面になっているのでlinux textリターンと入力してテキストモードでインストールします。

"Hostname Configuration"の画面では"manually"にしてvm1などとホスト名を入力します。

あとはhnakamur’s blog: CentOSのネットワークインストールの「libvirtに登録」と同様にしてlibvirtに登録します。

2009-11-18

Canon ドキュメントスキャナ imageFORMULA DR-150を購入

キヤノン:ドキュメントスキャナー DR-150
  • ScanSnap fi-5110E0Xは薄い紙だとダブルフィードになりやすい。が、同じ本で試すとDR-150は大丈夫。これは便利。
  • ACアダプタは別売りですが、通信用のUSBケーブル1本と給電用のUSBケーブル1本が付属してそれだけで使えます。さらに給電用のUSBケーブルは接続しなくても使えます(読み込みが遅くなりますが)。
  • Adobe Acrobatは付属していませんが、付属のCaptureOnTouchで取り込むとPDF保存するときに日英対応のOCRがかけられます。
  • ScanSnap fi-5110E0Xよりは斜めになりにくい感じ。CaptureOnTouchの[斜行補正]はオンにしているが、全く斜めにならないわけではない。ということはシートフィーダの性能が効いているのかな。
  • 300dpiなら読み取り速度は十分。400dpiはかなり遅い。
  • 白黒/200dpiと誤差拡散/200dpiの画質はいまいち。解像度は300dpiで使うことにした。
  • スキャンオプションで[先読みスキャン]、試しに[標準]にしてみたら読み込み速度がページの最下部だけ遅くなる。本によっては両面読み込みで1ページおきにページ最下部に横線が入るせいで、Kindleでの余白除去と自動ズームの倍率がページごとにかわるのが嫌なんですが、これで解消されるかと期待したが変わらず。結局[先読みスキャン]に戻しました。

2009-11-12

CentOSでheartbeatでVIP引き継ぎ

はじめに

Amazon.co.jp: Linux-DB システム構築/運用入門 (DB Magazine SELECTION): 松信 嘉範: 本とググってみつけたHot Linux - heartbeat(1.2.x)のインストール/設定(Redhat9,WhiteBoxEL4)などのページを参考に試しました。heartbeatの設定ファイルはv1形式にしました。

cent1 (192.168.122.21)とcent2 (192.168.122.22)の2台で相互監視する例を試しました。

インストール

$ sudo install heartbeat heartbeat-pils heartbeat-stonith
0002821: "yum install heartbeat" fails - CentOS Bug Trackerのバグのため、heartbeatのインストールはもう一度実行する必要がありました。
$ sudo install heartbeat

設定

ファイアウォールでUDPのポート694を開ける

言わずもがなということで巷の説明では省略されていますが、忘れててはまったので私の場合は注意が必要です。

$ sudo vi /etc/sysconfig/iptables

以下の行を適当なところに挿入します。

-A RH-Firewall-1-INPUT -p udp -m udp --dport 694 -j ACCEPT
$ sudo /etc/init.d/iptables restart
$ sudo /sbin/iptables -L

以下の行が含まれることを確認。

ACCEPT     udp  --  anywhere             anywhere            udp dpt:ha-cluster 

/etc/ha.d/ha.cf

cent1では以下のようにします。

use_logd yes

keepalive 500ms
deadtime 10
warntime 5
initdead 60

ucast eth0 192.168.122.22

auto_failback off
#auto_failback on

node cent1
node cent2

uuidfrom nodename

cent2ではucastの行を以下のようにします。

ucast eth0 192.168.122.21

当初uuidfrom nodenameの行を忘れてはまったので注意。この指定が無いと、/var/lib/heartbeat/hb_uuidをマシンのUUIDとして使うので、仮想イメージファイルをクローンして作ったためか同じ内容になってしまい、以下のようなエラーが延々とログに出ることになります。

heartbeat[14054]: 2009/11/12_18:17:32 WARN: nodename cent1 uuid changed to cent2
heartbeat[14054]: 2009/11/12_18:17:32 WARN: nodename cent2 uuid changed to cent1
heartbeat[14054]: 2009/11/12_18:17:32 WARN: nodename cent1 uuid changed to cent2

/etc/ha.d/haresources

プライマリのノードと仮想IPアドレスを設定します。ですのでcent1でもcent2でも同じ内容にします。

cent1 192.168.122.90

/etc/ha.d/authkeys

2台ともLAN内なので認証はcrcにしました。

auth 1
1 crc
$ sudo chmod 600 /etc/ha.d/authkeys

実験

cent1、cent2ともコマンドを実行する端末とは別に端末を起動しておいてtail -f /var/log/ha-logを実行しておくと動きを見られてよいです。

まず、cent1でheartbeatを起動します。

cent1$ sudo /etc/init.d/heartbeat start

起動してしばらくすると、仮想IPアドレスが設定されます。ipコマンドで確認するなら以下のようにします。

cent1$ /sbin/ip addr show eth0
2: eth0:  mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.21/24 brd 192.168.122.255 scope global eth0
    inet 192.168.122.90/24 brd 192.168.122.255 scope global secondary eth0:0
    inet6 fe80::5054:ff:fe12:3456/64 scope link 
       valid_lft forever preferred_lft forever

ifconfigで確認する場合は以下のようにします。

cent1$ /sbin/ifconfig -a eth0:0
eth0:0    Link encap:Ethernet  HWaddr 52:54:00:12:34:56  
          inet addr:192.168.122.90  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:10 Base address:0xc000

cent1だけ起動してcent2を起動しない場合はha.cfのinitdeadの設定値、この場合は60秒後に仮想IPアドレスが設定されました。

cent1を起動してすぐにcent2も起動した場合はcent1のログにLink cent2:eth0 upと出力されてから13秒後に仮想IPアドレスが設定されました。ha.cfのdeadtimeが10秒という設定なので、これ+αということのようです。

次に、cent2でheartbeatを起動します。

cent2$ sudo /etc/init.d/heartbeat start

ログを見て起動が完了したことを確認したら、cent1でheartbeatを停止してみます。

cent1$ sudo /etc/init.d/heartbeat stop

ログを見て仮想IPが引き継がれた旨が表示されたらipまたはifconfigで確認してみると無事引き継がれていることを確認できました。

2009-10-29

裁断機で本を切断してScanSnapでとりこんだPDFを画像ファイルにばらしてImageMagickで加工して再度PDFにしてみた

裁断機で本を切断してScanSnapで取り込むまで

前段階として裁断機で本を切断してScanSnapで取り込むところは、中身を捨てずに空間をすてる。漫画も本も iPhone に入れる全工程 | Lifehacking.jpと同じです。私は裁断機はPLUS PK-513を使っていて、ScanSnapはfi-5110E0Xです。

読み込む設定ですが、解像度は以前はスーパーファインにしてましたが、最近は容量削減のためファインにすることが多いです。白黒/カラーは自動判定にはせず切り替えて使います。白黒はモノクロ2値なのでグレースケールの書籍の場合はカラーにします。

また表紙カバーは別途フラットヘッドスキャナで取り込んでPDFファイルにしておきます。

PDFファイルの連結

表紙カバーと本体と裏表紙のPDFを連結して一旦1つのPDFにします。

Linuxだとpdftk - the pdf toolkitをつかえばよさそうです。私はMacBookを使っているのでMacPortsでインストールを試みたのですが、Install fails for gcc42 - libgfortran.a has no symbols?!と同じ問題にひっかかってインストールできていません。代わりに[mac] コマンドラインからpdfを結合する - Hirameki Inspirationで紹介されている方法を使っています。

/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py --output out.pdf in1.pdf in2.pdf in3.pdf ...

PDFファイルをページ毎に画像に分割

Apache PDFBox - Java PDF LibraryというJava向けのPDFライブラリ(以前はpdfbox.orgだったのですが最近Apacheのインキュベータに入ったようです)のExtractImageというクラスを利用します。事前にJavaのランタイムのインストールが必要です。旧バージョン0.7.3を使う場合は以下のコマンドを実行します。

java -cp PDFBox-0.7.3/lib/PDFBox-0.7.3.jar org.pdfbox.ExtractImages foo.pdf

実行するとカレントディレクトリにIm1-1.jpg, Im2-2.jpg, ...という具合に画像ファイルが作られます。JPEGになるはカラーで取り込んだ場合の話で、白黒の場合はTIFFファイルになります。この後の手順で扱いやすいようにディレクトリを作ってそちらに移動しておきます。もちろん、そもそも先にディレクトリを作っておいてそちらにバラしてもよいです。

ページごとの画像ファイルを加工

加工の目的

斜めになってしまったページを真っすぐにしたい

ScanSnapで取り込んだ画像は私のやり方が下手なのかもしれませんが、たいてい微妙に斜めになってしまいます。しかもページ毎に傾き度合いがばらついてしまいます。ScanSnapにも傾き補正機能がついているのですが、相当傾いていないと反応しないのと、ページ内に斜めの直線があると誤反応して斜めになってしまうことがあったので、結局使っていません。ちょっとぐらいの傾きは気にしないと割り切ったほうがいいと思いつつ、いつか綺麗にそろえたいと常々思っていました。Kindle DXで見ると特に気になってしまうんですよね、これが。

ファイルサイズを削減したい

グレースケールの本でも白黒でスキャンするとモノクロ2値になってしまってグレーの箇所が汚くなるのでカラーでスキャンしていますが、その後画像をグレースケールにするとかして少しでも容量を削減したい。ただしできるだけ見た目は綺麗に保ちたい。

画質を上げたい

カラーで取り込むとJPEGになるためか、文字の部分も色ムラができてKindle DXで見るときに、読めなくはないけど美しくない。一方、白黒で取り込んだTIFFはかなり美しくてみていてほれぼれします。でもグレースケールの本を白黒で取り込むと図とかでグレーの部分がきたなくなってしまうので、カラーで取り込まざるをえない。そこでJPEGを加工して少しでも綺麗にしたい。ただ、私の画像加工のスキルが低くて今はたいしたことができていません。

ImageMagickで加工

加工の仕方を試行錯誤することになるので手動だとやり直すのが大変なので、コマンドラインで実行できるImageMagickを使います。RubyのRakefileを書いてそこからImageMagickのconvertコマンドを実行するようにしてみました(RMagick使ったほうがいいかとも思いましたがImageMagickとRMagickのマニュアルを両方読むのが面倒だったので直接コマンドを実行することにしてしまいました)。

INPUT_DIR='./orig'
OUTPUT_DIR='./output'
PDF_OUTPUT_DIR='./output_pdf'

COVER_PAGE_WIDTH = 1710
COVER_PAGE_HEIGHT = 2444
PAGE_WIDTH = 1115
PAGE_HEIGHT = 1632

# page => [angle, x, y, type]
ADJUSTS = {
  1 => [0, 0, 0, :cover],
  2 => [0, 0, 0, :cover],
  3 => [0, 85, 42, :page],
  4 => [0, 110, 42, :page],
  5 => [0, 110, 42, :page],
  6 => [-0.27, 120, 42, :page],
  7 => [0.27, 100, 42, :page],
  8 => [-0.29, 100, 42, :page],
...(略)...
  1263 => [0.16, 100, 42, :page],
  1264 => [-0.16, 100, 42, :page],
  1265 => [0, 0, 0, :cover],
  1266 => [0, 0, 0, :cover],
};

task :conv do
  page = ENV['page'].to_i
  convert_page(page)
end

task :conv_all_pages do
  ADJUSTS.keys.sort.each {|page| convert_page(page)}
end

task :pdf_all_pages do
  ADJUSTS.keys.sort.each do |page|
    jpg_file = "#{OUTPUT_DIR}/%04d.jpg" % page
    pdf_file = "#{PDF_OUTPUT_DIR}/%04d.pdf" % page
    sh "convert #{jpg_file} #{pdf_file}"
  end
end

def convert_page(page)
  in_file = "#{INPUT_DIR}/Im#{page}-#{page}.jpg"
  out_file = "#{OUTPUT_DIR}/%04d.png" % page
  deg, x, y, type = ADJUSTS[page]
  case type
  when :cover
    w = COVER_PAGE_WIDTH
    h = COVER_PAGE_HEIGHT
    sh "convert #{in_file} -set option:distort:viewport #{w}x#{h}+#{x}+#{y} +distort SRT #{deg} -quality 50% -density 200 #{out_file}"
  when :page
    w = PAGE_WIDTH
    h = PAGE_HEIGHT
    #sh "convert #{in_file} -set option:distort:viewport #{w}x#{h}+#{x}+#{y} +distort SRT #{deg} -quality 50% -colorspace Gray -density 200 #{out_file}"
    #sh "convert #{in_file} -set option:distort:viewport #{w}x#{h}+#{x}+#{y} +distort SRT #{deg} -sharpen 0x1 -density 200 -normalize -colors 2 #{out_file}"
    #sh "convert #{in_file} -set option:distort:viewport #{w}x#{h}+#{x}+#{y} +distort SRT #{deg} +repage -density 200 -normalize -colors 2 #{out_file} && open #{out_file}"
    sh "convert #{in_file} -set option:distort:viewport #{w}x#{h}+#{x}+#{y} +distort SRT #{deg} +repage -density 200 -normalize -colors 2 #{out_file}"
  end
end

傾き補正の角度は元の画像ファイルをプレビューで開いてPixelStickというMac用のソフトで測っています。

ターミナルを2つ上げて1つはvimでRakefileを編集し、1つはrakeを実行するという感じでパラメータを調節しては変換して結果を見てというのをくり返します。このときはconvertした後openで結果を開くようにしておくとプレビューが開いて表示されるので手間が省けて便利です(コメントアウトしてあるshの行の最後)。ページ数の分だけひたすら繰り返すので、キーストローク数を最小にして効率を上げるのが重要です。私はCommand+TABでプレビューとターミナルを切り替え、ターミナルの2つのウィンドウはCommand+`(デフォルトはCommand+F1ですが変更しています)で切り替えています。

convertの引数は未だ試行錯誤中でこれがベストというのは見つけられていません(というよりImageMagickの使い方を勉強中です。オプションが多くて…)。

加工した画像を連結してPDFを作成

だいたい満足いくように各ページの画像を加工できたら、再び連結してPDFにします。ImageMagickを使ってconvert *.jpg out.pdfとするとすごく時間がかかるので、各ページごとにconvertでJPEGをPDFに変換して、上記の手順でPDFを連結します。

というわけで、相当手間と時間がかかるのですが、ページ毎に大きく傾いていたのがほぼ真っすぐになってKindle DXでも気分よく読めます。ですので苦労するだけのことはあります。

2009-10-09

keychainでssh-agentを管理

man keychainによるとkeychain - re-use ssh-agent and/or gpg-agent between loginsというものだそうです。

$ sudo aptitude install keychain
$ vi ~/.bash_profile

以下の内容で作成します。

# keychain
eval `keychain --nogui --eval ~/.ssh/id_rsa`

~/.ssh/id_rsa.pubも置いておかないとなんかエラーか警告が出たので置くようにしました。

yum infoで探すとCentOSでもrpmforgeにありました。が、今の構成では不要なので試してはいません。

CentOSの言語を日本語から英語に変える

インストールのときに日本語を選択しておくとタイムゾーンが自動的にAsia/Tokyoになって便利なのですが、コンソールで文字化けしているので(原因は未調査)、英語に切り替えることにしました。

# vi /etc/sysconfig/i18n
以下のように変更します。
#LANG="ja_JP.UTF-8"
LANG="en_US.UTF-8"
...

コミット済みのファイルを消してしまったときはgit resetで復旧

既にコミットしたファイルをローカルから消した後に復活させるのはgit resetコマンドでできます。

最近gitの練習も兼ねて/etc/以下のファイルを必要に応じてgit addで追加して管理しているのですが、例えばvirsh net-destroyを実行して設定ファイルが消えた場合は以下のようにして復旧します。

$ cd /
$ sudo git reset ./etc/libvirt/qemu/networks/default.xml

CentOSのネットワークインストール

KVMでCentOS 5.3のネットワークインストール

KVMでCentOSをテキストモードでインストールすると同様に仮想環境を作ったのですが、今度はネットワークインストールにしてみました。

$ wget ftp://ftp.riken.go.jp/Linux/centos/5.3/isos/i386/CentOS-5.3-i386-netinstall.iso
$ qemu-img create -f qcow2 vm10.qcow2 10G
$ sudo kvm -hda vm10.qcow2 -cdrom CentOS-5.3-i386-netinstall.iso -boot d -m 512 -curses

最初に"640 x 480 Graphic mode"と表示されたときにlinux text<ENTER>と押します。

途中でインストールメディアを聞かれるところでは、タイプをFTP、サーバーはftp.riken.go.jp、パスは/Linux/centos/5.3/os/i386/を指定します。

インストールするパッケージではServerのGUIなしにしてカステムでeditorsのvim-enhanced以外を全てオフにします。これでも合計650Mだそうです。

CentOS 5.3 のネットワークインストールでエラー - BitWalkerによるとCentOS 5.3のnetinstallにはメモリが512MB以上必要とのことです。

libvirtに登録

既存のKVMのゲストOSイメージをlibvirtに登録と同様ですが、ネットワークはブリッジではなくデフォルトのNATにして、-sオプションは不要なので外しました。詳しくはman virt-installで。

$ sudo virt-install -n cent1 -r 512 -vcpus=1 -f cent1.qcow2 -c /dev/null --os-type linux \
--accelerate --nographics -m 52:54:00:12:34:56

2009-10-01

WolframAlphaで数式を微分するときに定数を含める方法

derivativeでは定数とはみなされない

Wolfram|AlphaExamples - Calculus & Analysisではderivativeで微分するような例があるのですが derivative of a+b*t+c*t^2+d*t^3とやってみるとaなどもtの関数と思われてa'などが結果に入ってきてしまいます。

Dt[...]を試すが失敗

Click for copyable inputを見てDt[a+b*t+c*t^2+d*t^3, t, Constants -> {a,b,c,d}]を試すがエラー。AlphaはMathmaticaと全く同じという訳ではないようです。

D[...]でUse as math functionに切り替えればOK

D (∂) - Wolfram Mathematica Documentation Centerを見つけてD[a+b*t+c*t^2+d*t^3, t]とやってみるといけました。結果のページに表示されるUse as referring to derivative computations insteadのリンクを押すとderivativeコマンドと同様にa'などを含むようになります。そこからさらにUse as a math function insteadを押すとaは定数と扱うように戻ります。URLのパラメータを見るとmathの場合はa=*C.D-_*Function-がderivativeの場合はa=*C.D-_*DerivativesWord-と指定するようです。

2009-09-29

virsh consoleを使うためにUbuntuのシリアルコンソール設定

ゲストOSのシリアルコンソール設定

SerialConsoleHowto - Community Ubuntu Documentationを参考にしました。ゲストOSを起動してシリアルコンソールを設定します。

$ sudo vi /etc/event.d/ttyS0
以下の内容で新規にファイルを作成します。
# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again.

start on runlevel 2
start on runlevel 3
start on runlevel 4
start on runlevel 5

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

respawn
exec /sbin/getty 115200 ttyS0
grubの設定を行います。
$ sudo vi /boot/grub/menu.lst

titleの前にserialとterminalの行を追加し、kernelパラメータにconsoleのパラメータを2つ追加します。

...
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1 # ←この行を追加
terminal --timeout=5 serial console # ←この行を追加
title           Ubuntu 9.04, kernel 2.6.28-15-serveruuid            0ede7815-2475-4811-83b6-1970ab826e32
kernel          /boot/vmlinuz-2.6.28-15-server root=UUID=0ede7815-2475-4811-83b6
-1970ab826e32 ro quiet splash console=tty0 console=ttyS0,115200n8 # ←consoleパラメータを2つ追加
initrd          /boot/initrd.img-2.6.28-15-server

title           Ubuntu 9.04, kernel 2.6.28-15-server (recovery mode)uuid            0ede7815-2475-4811-83b6-1970ab826e32
kernel          /boot/vmlinuz-2.6.28-15-server root=UUID=0ede7815-2475-4811-83b6
-1970ab826e32 ro  single
initrd          /boot/initrd.img-2.6.28-15-server
...

ホストOS側のlibvirtのドメイン設定

DOMの設定ファイルにConsoles, serial & parallel devicesのconsoleタグが入っていなければゲストOSの設定を変更。

$ sudo vi /etc/libvirt/qemu/ubuntu.xml

以下のようにconsoleタグを追加。

...
    <console type='pty'>
      <source path='/dev/pts/4'/>
      <target port='0'/>
    </console>
  </devices>
</domain>

ゲストOSを止めた状態で反映。

$ sudo virsh define /etc/libvirt/qemu/ubuntu.xml

KVM/libvirtでUbuntu 9.04 server 64bit版サーバーをホストOS、32bit版サーバーをゲストOSとする環境構築

背景

Javaで4GB以上の最大メモリを使いたくてUbuntu 9.04 server 64bit版上で64bit版のJavaを使用していたのですが、32bit版でしか動かないバイナリのみ提供のとあるプログラムを動かす必要が出てきました。

Ubuntu Linux 64bit版で32bit向けバイナリを使えるようにする | おいぬま日報を参考にia32-libsを試してみましたが、いくつかライブラリが自動でインストールされたものの、お目当ての実行ファイルは結局動作せず。

武藤さんのdebian-amd64のページを見るとchrootでできるみたいですが、chrootがよくわかってない私がやるとはまりそうなのでこの道は止めました。

ということで、Ubuntu 9.04 server 64bit版をホストOSとし、Ubuntu 9.04 server 32bit版をゲストOSとする環境構築を行いました。

Ubuntu 9.04 Server 32bit版をゲストOSとしてインストール

うまくいかなかった手順

当初はKVMでCentOSをテキストモードでインストールすると同様にUbuntu 9.04 Server 32bit版のCD-ROM ISOイメージからインストールしようとしました。しかし、"640 x 480 Graphic mode"からリターンキーで進んでも一旦コンソールになったあと再び"640 x 480 Graphic mode"になってしまいます。手元の環境でVirtualBoxでインストールしながら同じようにリターンキーを押していくということも試しましたが、進んでるかどうかさっぱりわからないので止めました。

作業環境からホストOSにvnc viewerでアクセスできるようなネットワーク構成を組んでいればそれでもよかったのですが、このときは外出先からアクセスしていてsshとhttp/httpsでしかアクセスできないのでこの手は使えませんでした。

ubuntu-vm-builderを使うと簡単にインストールできます(でも結局vncは必要)

ubuntu-vm-builderでのゲストOSインストール

調べてみるとKVM Create Guests - Community Ubuntu Documentationでubuntu-vm-builderという便利なものが紹介されていました。これだと自動でインストールしてくれます。

$ sudo aptitude install ubuntu-vm-builder
$ sudo ubuntu-vm-builder --addpkg vim openssh-server --libvirt qemu:///system

デフォルトで作られるアカウントのID/パスワードはubuntu/ubuntuでした。

--libvertオプションはlibvirtの管理下に登録するために必要とのこと。

--addpkgでopenssh-serverを指定しておくと最初からsshサーバーがインストールされて、ゲストOSを起動後ホストOSからsshでアクセスできるとのことなんですが、なんかうまくいかなかったようです。で、この作業をしていたときは家だったのでゲストOS起動後、LAN経由でvnc viewerでアクセスできたので、なんとかなりました。ただし、vncサーバーがデフォルトではlocalhostからしかアクセスできないようになっているので設定変更と反映が必要でした。

ゲストOSのIPアドレスを固定するようにホストOSのDHCPを設定

まずゲストOSの設定ファイルを見て

$ sudo vi /etc/libvirt/qemu/ubuntu.xml

MACアドレスを確認します。

    ...
    <interface type='network'>
      <mac address='52:54:00:52:42:d9'/>
      <source network='default'/>
      <model type='virtio'/>
    </interface>
    ...

DHCPの設定を変更します。

$ sudo vi /etc/libvirt/qemu/networks/default.xml

適当に自動割り当てのrangeを狭くして、MACアドレスを指定した行を追加します。

<network>
  <name>default</name>
  <uuid>ae240447-f8ad-b557-a039-4e8bae931331</uuid>
  <forward mode='nat'/>
  <bridge name='virbr1' stp='on' forwardDelay='0' />
  <ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.100' end='192.168.122.254' />
      <host mac='52:54:00:52:42:d9' name='ubuntu' ip='192.168.122.11' />
    </dhcp>
  </ip>
</network>

保存したらdnsmasqを再起動します。

まずdnsmasqのPIDを調べてkillします。KVM以外でdnsmasqを動かしていなければ以下のコマンドで調べてそのままkillできます。

$ sudo kill `ps --no-heading -o pid -C dnsmasq`

ネットワーク設定をlibvirtに反映します。

$ sudo virsh net-define /etc/libvirt/qemu/networks/default.xml

ゲストOS上のvncサーバーにホストOS以外のマシンからアクセスできるようにする設定

まず現状どうなっているかの確認はpsでkvmのコマンドラインを見ます。

$ ps ww -C kvm

ホストOS上で以下の設定を行います。

$ sudo vi /etc/libvirt/qemu/ubuntu.xml

このファイルについてはlibvirt: Domain XML formatに説明があります。

以下のように<devices>のセクションにvncのエントリを追加し、listen='0.0.0.0'を追加します。

    ...
    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
  </devices>
</domain>

編集したら以下のコマンドで反映します(ゲストOSは予め止めておきます)

$ sudo virsh define /etc/libvirt/qemu/ubuntu.xml

なおGraphical framebuffersの説明によるとport='-1'という書き方は古くてautoport='yes'と書けとのことでしたが、virsh defineで反映すると勝手にport='-1'も追加されていました。

再度以下のコマンドを実行して

$ ps ww -C kvm

-vncのパラメータが-vnc 0.0.0.0:0となっていればOKです。

ホストOSと同一LANにある別のマシンからゲストOSにアクセス

上の-vncのパラメータのコロンの後がディスプレイ番号(ポート番号はディスプレイ番号+5900)なので、そこにアクセスします。

MacBook/Snow LeopardからChicken of the VNC | Get Chicken of the VNC at SourceForge.netを使ってアクセスしました。

ゲストOS上にsshサーバーをインストール

vnc viewerでつなぐとコンソールのログインプロンプトが出ているのでログインしてopenssh-severをインストールします。

$ sudo aptitude install openssh-server

2009-09-28

vimで制御コードを16進表示

Just another Ruby porter, 2006-6-aで知りました。
:set binary
:set display=uhex

2009-08-27

NAT構成ネットワークでkeepalivedによるロードバランサの実験

libvirtでNAT構成にするための設定ApacheのServer-Side Includesの設定の準備ができたところで、いよいよロードバランサの実験です。

ホストOS上の/etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
    state BACKUP
    interface br0
    virtual_router_id 50
    priority 200
    advert_int 1
    garp_master_delay 10
    virtual_ipaddress {
        192.168.11.100
    }
}

virtual_server 192.168.11.100 80 {
    delay_loop 1
    lvs_sched rr
    lvs_method NAT #DR
    protocol TCP
    real_server 192.168.122.11 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status 200
            }
            connect_timeout 3
        }
    }
    real_server 192.168.122.12 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status 200
            }
            connect_timeout 3
        }
    }
}

実験用スクリプト

$ while :; do curl http://192.168.11.100; env LANG=C date; sleep 1; done

実行結果はこんな感じ。

Hello, this is vm11.
Thu Aug 27 02:47:03 JST 2009
Hello, this is vm10.
Thu Aug 27 02:47:05 JST 2009
Hello, this is vm11.
Thu Aug 27 02:47:06 JST 2009
Hello, this is vm10.
...(略)...

vm10でhttpdを止めてみるとvm11のみにいくようになりました。その前に

curl: (52) Empty reply from server

が1回出るときと1回も出ずにスムーズにvm11に切り替わるときがありました。

その後、vm10でhttpdを再開してみたのですが、引き続きvm11にしかいきません。ホストOSで

# /etc/init.d/keepalived reload

と実行してみると再びvm10とvm11に交互に投げるようになりました。inhibit_on_failureというオプションがあるぐらいなので指定しない場合は復活するのかと思っていたのですが。これはこういうものなのかは今後調査したいと思います。

ApacheのServer-Side Includesの設定

背景

ロードバランサの実験用にゲストOSのホスト名を入れたindex.htmlを

Hello, this is vm10.

といった感じで作っていたのですが、ゲストOSごとに書き換えずに済ませたいので Server-Side Includesを使う事にしました。

設定

mod_includeを参考にしました。CentOSの/etc/httpd/conf/httpd.confには

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
は設定済みだったので、<Directory "/var/www/html">セクションのOptions行に
    Options Indexes Includes FollowSymLinks
のようにIncludesを追加し、DirectoryIndexの行に
DirectoryIndex index.html index.shtml index.html.var
のようにindex.shtmlを追加しました。

そして、index.htmlをindex.shtmlに改名して

Hello, this is <!--#exec cmd="echo -n `hostname`"-->.
のように変更しました。

最初は

Hello, this is <!--#echo var="SERVER_NAME"-->.
にしたのですが、ロードバランサ経由だとリクエストURLのホスト名もしくはIPアドレスになってしまうのでだめでした。

次は

Hello, this is <!--#exec cmd="hostname"-->.
としたのですが、ドットの前に改行が入ってしまうことが判明したので、echo -n `hostname`に変更しました。

2009-08-26

libvirtでNAT構成にするための設定

ブリッジを止めてNATに切り替えたわけ

KVMのゲストOSのネットワークをブリッジにするの環境でkeepalivedでのVRRPの実験は成功したのですが、DSR構成でのロードバランサの実験がどうもうまくいきませんでした。仮想環境でのネットワーク構築がよくわかっていない私がいきなり上級者編のDSRにチャレンジというのに無理があったということで、まずはNAT構成でチャレンジすることにしてみました。

libvirtでNAT構成

libvirt: Wiki: Networkingを参考にしました。また、今まではゲストOSを実運用に近い設定にしようとして固定IPにしていましたが、virt-cloneでゲストOSイメージをコピーしたあとにゲストOS毎に設定を変えるのが面倒なので、今回から極力ゲストOS毎の設定変更箇所を少なくするという方針に変更しました。

試行錯誤しながらホストOSでのlibvirtの設定変更を変更したので、手順は無しで設定ファイルだけメモしておきます。

ホストOS (Ubuntu) の設定

/etc/libvirt/qemu/networks/default.xml

<network>
  <name>default</name>
  <uuid>212ea219-055f-bd26-1c76-52817e607642</uuid>
  <bridge name="virbr%d" />
  <forward mode="nat"/>
  <ip address="192.168.122.1" netmask="255.255.255.0">
    <dhcp>
      <range start="192.168.122.100" end="192.168.122.254" />
      <host mac="52:54:00:12:34:56" name="vm10" ip="192.168.122.11" />
      <host mac="52:54:00:12:34:57" name="vm11" ip="192.168.122.12" />
    </dhcp>
  </ip>
</network>

/etc/libvirt/qemu/vm10.xml

<domain type='kvm'>
  <name>vm10</name>
  <uuid>35e92166-78c8-641f-15d7-5a30af377d55</uuid>
  <memory>524288</memory>
  <currentMemory>524288</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch='i686' machine='pc'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/bin/kvm</emulator>
    <disk type='file' device='disk'>
      <source file='/home/hnakamur/kvm_work/vm10.qcow2'/>
      <target dev='hda' bus='ide'/>
    </disk>
    <disk type='file' device='cdrom'>
      <target dev='hdc' bus='ide'/>
      <readonly/>
    </disk>
    <interface type='network'>
      <mac address='52:54:00:12:34:56'/>
      <source network='default'/>
    </interface>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target port='0'/>
    </console>
  </devices>
</domain>

/etc/sysctl.confでは以下の設定変更をしてsysctl -pで読み込みました。

net.ipv4.ip_forward=1

/etc/resolv.conf

nameserver 192.168.122.1
nameserver 192.168.11.1

ゲストOS (CentOS) の設定

/etc/sysconfig/network (ホスト名はDHCPで設定するので空にしました)

NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=

/etc/resolv.conf

nameserver 192.168.122.1

/etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
DNS1=192.168.122.1

(追記) その後試していると/etc/resolv.confの設定が消されてしまってeth0が上がらないことがありました。/etc/sysconfig/network-scripts/ifcfg-eth0にDNS1=で指定しておくとOKでした。これがまっとうなのかはわかりませんが、とりあえずこれで。

(2009-08-27追記) CentOSのDeployment Guideの14.2. Interface Configuration Filesに説明がありました。PEERDNSがyesの場合DNS1とDNS2に指定した値で/etc/resolv.confが修正されます。dhcpの場合PEERDNSのデフォルト値はyesです。

ホストOSでのlibvirtの設定の試行錯誤

手順として整理したものは無いのですが、どんな試行錯誤をしたかのメモを書いておきます。

/etc/libvirt/qemu/networks/default.xmlの変更と反映での試行錯誤

libvirt: Wiki: Networkingを参考にしたのですが、結局のところvirshを起動してhelpコマンドで出てくるネット関連のコマンド(net-*)を手当たり次第に試して変更しました。net-editで変更してみたり、net-destroyやnet-undefineで消してからnet-createで作り直したり。net-destroyかnet-undefineを実行したときは、/etc/libvirt/qemu/networks/default.xmlが消えてしまって慌てたりしました。事前にバックアップをとっておいたほうがいいです。

また途中でnet-editを実行したときに

error: invalid network pointer in no network with matching uuid
というエラーが出て困りました。どうやら、/etc/libvirt/qemu/networks/default.xmlを直接エディタで変更したのがよくなかったようで、常にnet-editで編集するようにしておいたほうがいいみたいです。あと、確か元々の/etc/libvirt/qemu/networks/default.xmlにはuuidの要素は無かったのが、net-editで見たときは入っていました。/etc/libvirt/qemu/networks/default.xmlはテンプレートみたいなものでvmを作るときにそこからコピーされるのかとも思ったのですが、net-editで編集した結果は/etc/libvirt/qemu/networks/default.xmlに反映されるようです。そのときにどこか別の場所にも反映されているのかな、まだよくわかってないです。

ゲストOSでのlibvirt組み込みのDNSサーバーdnsmasqの設定変更の試行錯誤

libvirt: Wiki: Networking

If you are already running dnsmasq on your machine, please see libvirtd and dnsmasq.
という説明があります。libvirt: Wiki: Libvirtd and dnsmasqを読んで、psで見てみるとdnsmasqのプロセスがありますが/etc/dnsmasq.confはありませんでした。というわけでこれはlibvirtが起動したもののようです。ただ、/etc/init.d/dnsmasqとかはないんですよね。Bug #231060 in libvirt (Ubuntu): “packages dnsmasq and libvirt-bin conflict with each other”とかが関係ありそうですが、とりあえずスルーしました。

libvirtのネットワークをうまく設定できた今の状態ではpsで見るとこんな感じです。

# ps auxww|grep dnsmasq
root      5077  0.0  0.0   2076   564 pts/7    S+   00:52   0:00 grep dnsmasq
nobody   31008  0.0  0.0   2388   716 ?        S    Aug26   0:00 dnsmasq --strict-order
 --bind-interfaces --pid-file=/var/run/libvirt/network/default.pid --conf-file=  
--listen-address 192.168.122.1 --except-interface lo --dhcp-range 192.168.122.100,192.168.122.254
 --dhcp-host 52:54:00:12:34:56,vm10,192.168.122.11 --dhcp-host 52:54:00:12:34:57,vm11,192.168.122.12

こうなるまでにいろいろ試行錯誤しました。/etc/libvirt/qemu/networks/default.xmlの<dhcp>タグの設定に対応していることはわかったのですが、viやvirsh net-editで変更するだけでは反映されないようなので、killして上げ直そうとしたのですが起動方法をまた試行錯誤するはめに。どうやらnet-startのときに同時にあがるのかと思いきや

virsh# net-start default
error: Failed to start network default
error: internal error network is already active
というエラーになったり。1

今、再度試してみたところ以下の手順でとりあえず変更できることを確認しました。

virsh # net-destroy default

ここでviで/etc/libvirt/qemu/networks/default.xmlを編集

virsh # net-create /etc/libvirt/qemu/networks/default.xml
Network default created from /etc/libvirt/qemu/networks/default.xml

net-createを実行した時点でdnsmasqのプロセスが上がっていました。

さらに一覧を確認して自動実行する設定にします。

virsh # net-list --all
Name                 State      Autostart
-----------------------------------------
default              active     no
virsh # net-autostart default
error: failed to mark network default as autostarted
error: Failed to create symlink '/etc/libvirt/qemu/networks/autostart/default.xml' 
to '/etc/libvirt/qemu/networks/default.xml': File exists

別端末にて/etc/libvirt/qemu/networks/autostart/default.xmlというシンボリックリンクを削除します。

# ls -l /etc/libvirt/qemu/networks/autostart/default.xml 
lrwxrwxrwx 1 root root 38 Aug 26 20:43 /etc/libvirt/qemu/networks/autostart/default.xml -> /etc/libvirt/qemu/networks/default.xml
# rm /etc/libvirt/qemu/networks/autostart/default.xml

これでようやく設定変更できた状態でdnsmasqが起動できたと思ったら今度は、ゲストOSの変更前のIPアドレスがキャッシュされて残っていたようでdigコマンドで引いても古い値を返されてしまいました。そこでkillして

# dnsmasq --clear-on-reload

を実行した後再度killしてvirshでnet-destroy、net-createとして再起動などとしてなんとかdigで新しい設定のIPアドレスが返されるところまでこぎつけました。このへんの手順も試行錯誤してたまたま見つけただけで、まっとうな手順はまだよくわかっていません。が、とりあえず目的は達成できたのでよしということで。

DHCPの恩恵

ホストOSもゲストOSも192.168.122.1のdnsmasqを使うようにしたので、/etc/hostsからvm10とvm11のエントリを削除できました。DHCPといっても、/etc/libvirt/qemu/networks/default.xmlの<host>タグでMACアドレスに対してホスト名とIPアドレスを指定しているので、各vmのIPアドレスが変動することはありません。

2009-09-29追記

  1. これはdnsmasqのプロセスが残っていたからでした。単にpsでdnsmasqのPIDを調べてkillした後、net-defineコマンドでxmlの内容を反映し、net-startコマンドでdnsmasqを起動します。ちなみに、net-destroyは定義ファイルを削除するのでやりすぎです。

2010-09-19追記

定義ファイルごと削除されるのはnet-undefineを実行したときです。net-destroyはdnsmasqのプロセスを止めます。

2010-12-16追記

DHCPで運用しているとゲストを上げたまま一日ぐらいたつとゲストのIPアドレスが消失してネットワークが繋がらなくなるという現象を何度か体験しました。仕方が無いのでDHCPはやめて静的にIPアドレスを指定する運用に切り替えました。

2009-08-25

QEMU WikiのSlirpやTapについての解説がわかりやすい

QemuNetwork - #qemu WikiからたどれるSlirpやTapの解説が非常に分かりやすかったです。後から読み返すこともありそうなのでメモ。

  • Slirpについての説明
    • ルート権限が無くても使えます。→Slirpによるネットワークはuser mode networkingあるいは略してuser networkingとかuser-netとも呼ばれます。
    • Slirp自体はダイアルアップの時代にSLIP接続とのやりとりをソケットに見せかけるために作られたプログラムのことです。
    • KVMのネットワークページのUser Networkingセクションに対応します。
  • Tapに付いての説明
    • The 'tap' deviceの項とNote5:によると、Tapはホスト・ゲスト間の通信に使われるそうです。LinuxやBSDのカーネルでは直接eth0にパケットを送るということはできないので、間にtap0を挟む必要があるということです。で、tap0からホストを宛先にして送ればホストのeth0に届くということになります。
    • Possibility 2: NAT routing with one "external" net, and one "virtual internal" LANsがKVMのネットワークページのprivate virtual bridgeセクションに対応します。
    • Possibility 3: NO routing, one LAN made up of real and virtual devicesがKVMのネットワークページのpublic bridgeセクションやKVM Networking - Community Ubuntu DocumentationのCreating a network bridge on the hostセクションに対応します。

WiresharkのCLI版tsharkのインストール

Wiresharkとは

WiresharkはネットワークプロトコルアナライザEtherealの後継にあたるらしい。

インストール

リモートのサーバーにsshで入って使うことを想定しているのでGUI版ではなくCLI版を使います。CLI版のコマンドはtsharkです。

CentOS 5.2の場合

# yum install wireshark

ちなみにGUI版のパッケージ名はwireshark-gnome

Ubuntu 9.04の場合

$ sudo aptitude install tshark

ちなみにGUI版のパッケージ名はwireshark

テスト

CLI版のコマンドはtsharkです。

# tshark -n -i br0 tcp port 80

別の端末で以下のコマンドを実行。

$ telnet 192.168.11.241 80
GET /

tsharkの端末で^Cを入力。出力結果はこんな感じ。

# tshark -n -i br0 tcp port 80
Running as user "root" and group "root". This could be dangerous.
Capturing on br0
  0.000000 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=1738335 TSER=0 WS=6
  0.000905 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=3965771 TSER=1738335 WS=4
  0.000978 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [ACK] Seq=1 Ack=1 Win=5888 Len=0 TSV=1738335 TSER=3965771
  1.362928 192.168.11.102 -> 192.168.11.241 HTTP GET /
  1.363635 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [ACK] Seq=1 Ack=8 Win=5792 Len=0 TSV=3967134 TSER=1738471
  1.364764 192.168.11.241 -> 192.168.11.102 HTTP Continuation or non-HTTP traffic 
  1.364829 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [ACK] Seq=8 Ack=22 Win=5888 Len=0 TSV=1738471 TSER=3967135
  1.364852 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [FIN, ACK] Seq=22 Ack=8 Win=5792 Len=0 TSV=3967136 TSER=1738471
  1.365315 192.168.11.102 -> 192.168.11.241 TCP 36674 > 80 [FIN, ACK] Seq=8 Ack=23 Win=5888 Len=0 TSV=1738471 TSER=3967136
  1.366978 192.168.11.241 -> 192.168.11.102 TCP 80 > 36674 [ACK] Seq=23 Ack=9 Win=5792 Len=0 TSV=3967138 TSER=1738471
^C10 packets captured

ちなみにtcpdumpの場合はこんな感じ。

# tcpdump -n -i br0 tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br0, link-type EN10MB (Ethernet), capture size 96 bytes
11:49:01.942466 IP 192.168.11.102.36673 > 192.168.11.241.80: S 3722872408:3722872408(0) win 5840 <mss 1460,sackOK,timestamp 1722908 0,nop,wscale 6>
11:49:01.943604 IP 192.168.11.241.80 > 192.168.11.102.36673: S 1321486056:1321486056(0) ack 3722872409 win 5792 <mss 1460,sackOK,timestamp 3811486 1722908,nop,wscale 4>
11:49:01.943673 IP 192.168.11.102.36673 > 192.168.11.241.80: . ack 1 win 92 <nop,nop,timestamp 1722909 3811486>
11:49:04.794205 IP 192.168.11.102.36673 > 192.168.11.241.80: P 1:8(7) ack 1 win 92 <nop,nop,timestamp 1723194 3811486>
11:49:04.795714 IP 192.168.11.241.80 > 192.168.11.102.36673: . ack 8 win 362 <nop,nop,timestamp 3814337 1723194>
11:49:04.795782 IP 192.168.11.241.80 > 192.168.11.102.36673: P 1:22(21) ack 8 win 362 <nop,nop,timestamp 3814338 1723194>
11:49:04.795818 IP 192.168.11.102.36673 > 192.168.11.241.80: . ack 22 win 92 <nop,nop,timestamp 1723194 3814338>
11:49:04.795838 IP 192.168.11.241.80 > 192.168.11.102.36673: F 22:22(0) ack 8 win 362 <nop,nop,timestamp 3814339 1723194>
11:49:04.796667 IP 192.168.11.102.36673 > 192.168.11.241.80: F 8:8(0) ack 23 win 92 <nop,nop,timestamp 1723194 3814339>
11:49:04.798567 IP 192.168.11.241.80 > 192.168.11.102.36673: . ack 9 win 362 <nop,nop,timestamp 3814341 1723194>
^C
10 packets captured
10 packets received by filter
0 packets dropped by kernel

2009-08-22

CentOS-Testingからkeepalivedを入れてVRRPの実験

インストール

# yum --enablerepo=c5-testing install keepalived

ファイアウォール設定

keepalivedを利用する際に気をつけておくこと - よかろうもん!を参考にしました。

iptables設定変更

# vi /etc/sysconfig/iptables

変更内容

--- /etc/sysconfig/iptables     2009/08/23 00:54:44     1.3
+++ /etc/sysconfig/iptables     2009/08/23 07:47:37
@@ -15,6 +15,7 @@
 -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
 -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
+-A RH-Firewall-1-INPUT -m state --state NEW -p 112 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT

man iptablesして確認したところ、-pの後にしているのはプロトコル番号。/etc/protocolsに

vrrp    112     VRRP            # Virtual Router Redundancy Protocol

という行があるので112ではなくvrrpとも書けるが、他が数値での指定なので合わせた。ちなみにRFC3768によると使用するポート番号も112。

iptables再起動

# /etc/init.d/iptables restart

VRRPによる仮想IP設定

# vi /etc/keepalived/keepalived.conf

作成内容

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 200
    advert_int 1
    garp_master_delay 5
    virtual_ipaddress {
        192.168.11.240
    }
}

実IPアドレスが192.168.11.241, 192.168.11.242の2台で仮想IPアドレスが192.168.11.240という想定です。priorityはもう1台では100などと違う値にします。

RFC3768によるとAuthentication Type 1, Authentication Type 2はRFC2338との互換性のために残されているが使用されないとのこと。なので、Authentication Type 0つまり認証無しということでkeepalivedのauthentication {}の部分は指定しない。

keepalived起動およびサービス設定

# /etc/init.d/keepalived start
# chkconfig keepalived on

CentOSのyumレポジトリにCentOS-Testingを追加

AdditionalResources/Repositories - CentOS WikiのCentOS-Testingの項を読んで位置づけを理解した上で追加。

# cd /etc/yum.repos.d
# wget http://dev.centos.org/centos/5/CentOS-Testing.repo

priorityを追加しておく。

# vi CentOS-Testing.repo

変更内容

--- /etc/yum.repos.d/CentOS-Testing.repo        2009/08/22 08:43:19     1.1
+++ /etc/yum.repos.d/CentOS-Testing.repo        2009/08/22 08:43:31
@@ -4,6 +4,7 @@
 enabled=0
 gpgcheck=1
 gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing
+priority=21
 
 # CentOS-Testing:
 # !!!! CAUTION !!!!

普段はenabled=0にしておいて、必要な際はyum実行時に--enablerepo=c5-testingをつけて使う。

試行錯誤でheartbeatを設定して動作確認するがうまくいかず

HAクラスタシステム構築(Heartbeat+DRBD) - CentOSで自宅サーバー構築を参考に/etc/ha.d/haresourcesという設定ファイルを作り、それを変換して/var/lib/heartbeat/crm/cib.xmlを作ってみた。Linux HAのharesources2cib.pyについての説明ページのConversion ExamplesのActive/Active Two IP address configurationの設定をまねて/etc/ha.d/haresourcesを作成。

# vi /etc/ha.d/haresources

作成内容

vm10 192.168.11.241
vm11 192.168.11.242

これを変換して/var/lib/heartbeat/crm/cib.xmlを作成。

# cd /var/lib/heartbeat/crm
# mv cib.xml cib.xml.orig
# /usr/lib/heartbeat/haresources2cib.py --stdout -c /etc/ha.d/ha.cf /etc/ha.d/haresources > cib.xml

vm10とvm11でheartbeat起動

# /etc/init.d/heartbeat start

crm_monでモニター

# /usr/sbin/crm_mon -i 3

しかし、vm10ではvm10しか一覧にしか出ないし、vm11ではvm11しか一覧に出ない。OFFLINEからonlineになるまでも数分ぐらいかかるし。なんだかよくわからないが、うまくいってないようだ。

とりあえず起動時に上げないようにしておく。

# chkconfig heartbeat off

EPELからheartbeatをインストール

インストール試すが依存関係で失敗

# yum install heartbeat

すると依存するlibnet.so.1が無いというエラー発生

Resolving Dependencies
--> Running transaction check
---> Package heartbeat.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: libstonith.so.1 for package: heartbeat
--> Processing Dependency: libpils.so.1 for package: heartbeat
--> Processing Dependency: libltdl.so.3 for package: heartbeat
--> Processing Dependency: libnet.so.1 for package: heartbeat
--> Running transaction check
---> Package libtool-ltdl.i386 0:1.5.22-6.1 set to be updated
---> Package heartbeat-stonith.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: net-snmp-libs for package: heartbeat-stonith
--> Processing Dependency: libnetsnmp.so.10 for package: heartbeat-stonith
---> Package heartbeat-pils.i386 0:2.1.4-9.el5 set to be updated
---> Package heartbeat.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: libnet.so.1 for package: heartbeat
--> Running transaction check
---> Package net-snmp-libs.i386 1:5.3.2.2-5.el5_3.2 set to be updated
---> Package heartbeat.i386 0:2.1.4-9.el5 set to be updated
--> Processing Dependency: libnet.so.1 for package: heartbeat
--> Finished Dependency Resolution
heartbeat-2.1.4-9.el5.i386 from epel has depsolving problems
  --> Missing Dependency: libnet.so.1 is needed by package heartbeat-2.1.4-9.el5.i386 (epel)
Error: Missing Dependency: libnet.so.1 is needed by package heartbeat-2.1.4-9.el5.i386 (epel)

libnet.soを求めて(失敗の巻)

libnet.soを含むパッケージを調べる。

# yum provides libnet.so
...(略)...
1463 packages excluded due to repository priority protections
1:java-1.6.0-openjdk-1.6.0.0-0.25.b09.el5.i386 : OpenJDK Runtime Environment
Matched from:
Other       : libnet.so



1:java-1.6.0-openjdk-1.6.0.0-0.30.b09.el5.i386 : OpenJDK Runtime Environment
Matched from:
Other       : libnet.so



1:java-1.6.0-openjdk-1.6.0.0-1.2.b09.el5.i386 : OpenJDK Runtime Environment
Matched from:
Other       : libnet.so

heartbeatがOpenJDKに依存しているってほんとかと思いつつ一応入れてみる。まずどこのレポジトリか確認。

# yum info java-1.6.0-openjdk

によるとupdatesレポジトリにあるらしい。

# yum install java-1.6.0-openjdk

libnet.soがインストールされたか確認

# rpm -ql java-1.6.0-openjdk | grep libnet
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/jre/lib/i386/libnet.so

ここに入るってことはOpenJDKしかみないよな。こんなとこにLD_LIBRARY_PATH通すとも思えないし。

yum install heartbeatを再度試すがやはり同じエラーが出ました。ということでOpenJDKを依存パッケージごとアンインストールします。

# yum remove java-1.6.0-openjdk giflib jpackage-utils libXtst

libnet.soを求めて(成功の巻)

libnetで検索してみる

# yum search libnet
...(略)...
=============================== Matched: libnet ================================
echoart.i386 : Responds to or drops ICMP echo requests packets
libnet.i386 : Routines to help with network packet contruction and handling
libnet-devel.i386 : Development files for the libnet library
libnet10.i386 : High-level API (toolkit) to construct and inject network packets
libnet10-devel.i386 : Development files for the libnet library
libnetfilter_conntrack.i386 : Netfilter conntrack userspace library
libnetfilter_conntrack-devel.i386 : Header files, libraries and development
                                  : documentation for libnetfilter_conntrack.
perl-Net-ARP.i386 : Create and send ARP packets
perl-Net-TFTP.noarch : TFTP Client class

libnetとかlibnet10がそれっぽい。

libnetを入れてみる

# yum install libnet

内容を確認

# rpm -ql libnet | lv

/usr/lib/libnet.aはあるが、libnet.soは確かに無い。

libnet10を入れてみる

# yum install libnet10

内容を確認

# rpm -ql libnet10 | lv

/usr/lib/libnet10.so.0というファイルならあったがlibnet.soはない。

libnetとlibnet10をアンインストール後、どのレポジトリか確認。

# yum remove libnet libnet10
# yum info libnet

extrasと判明。extrasからlibnet*を除外。

# vi /etc/yum.repos.d/Cent-Base.repo

変更内容

--- /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 15:08:54     1.4
+++ /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 15:22:08
@@ -48,7 +48,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
-exclude=heartbeat-*
+exclude=heartbeat-*,libnet*
 
 #additional packages that extend functionality of existing packages
 [centosplus]

再度確認

# yum info libnet

今度はrpmforgeでヒットしたので、ここからも除外

# vi /etc/yum.repos.d/rpmforge.repo

変更内容

--- /etc/yum.repos.d/rpmforge.repo      2009/08/21 09:09:14     1.2
+++ /etc/yum.repos.d/rpmforge.repo      2009/08/21 15:22:29
@@ -10,3 +10,4 @@
 gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
 gpgcheck = 1
 priority = 11
+exclude=libnet*
# yum info libnet

これでRepo: epelになったので、インストール。

# yum install libnet
# rpm -ql libnet | lv

/usr/lib/libnet.so.1が含まれている事を確認。

heartbeatのインストール再実行して成功

# yum install heartbeat
...(略)...
Dependencies Resolved

================================================================================
 Package                Arch      Version                    Repository    Size
================================================================================
Installing:
 heartbeat              i386      2.1.4-9.el5                epel         1.6 M
Installing for dependencies:
 heartbeat-pils         i386      2.1.4-9.el5                epel          90 k
 heartbeat-stonith      i386      2.1.4-9.el5                epel         169 k
 libtool-ltdl           i386      1.5.22-6.1                 base          37 k
 net-snmp-libs          i386      1:5.3.2.2-5.el5_3.2        updates      1.2 M
...(略)...

今度は無事インストールできました。今回の教訓は先にexcludeを調整して希望のパッケージが希望のレポジトリから取得できるようにすることが大切ということです。

CentOSのyumレポジトリにEPELを追加

EPELを追加してみる理由

AdditionalResources/Repositories - CentOS WikiExtra Packages for Enterprise Linux (EPEL)というサードパーティレポジトリが紹介されていました。

CentOSでheartbeatを使おうとしたがうまくいかずでインストールしたheartbeatはyum info heartbeatで確認したところバージョンは2.1.3でextrasリポジトリからインストールされたもの。

一方、RepoView: "Fedora EPEL 5 - i386"ではheartbeat-2.1.4-9.el5.i386とこちらのほうが新しい。というわけで試してみることに。

まずextrasリポジトリから入れたheartbeatパッケージを削除

heartbeatを入れた際に同時に入れられたパッケージ名を確認

# yum list installed | grep heartbeat
heartbeat.i386                          2.1.3-3.el5.centos             installed
heartbeat-pils.i386                     2.1.3-3.el5.centos             installed
heartbeat-stonith.i386                  2.1.3-3.el5.centos             installed

アンインストール

# yum remove heartbeat heartbeat-pils heartbeat-stonith

EPELのセットアップ

AdditionalResources/Repositories - CentOS WikiのEPELのセクションに従ってセットアップ

EPELを有効にするためのrpmをインストール

$ wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm
# rpm -ivh epel-release-5-3.noarch.rpm

EPELのpriorityを設定

# vi /etc/yum.repos.d/epel.repo

変更内容

--- epel.repo   2009/08/21 12:50:02     1.1
+++ epel.repo   2009/08/21 12:59:18
@@ -6,6 +6,7 @@
 enabled=1
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
+priority=12
 
 [epel-debuginfo]
 name=Extra Packages for Enterprise Linux 5 - $basearch - Debug

base, updates, addons, extrasからはheartbeat-*を除外

# vi /etc/yum.repos.d/CentOS-Base.repo

変更内容

--- CentOS-Base.repo    2009/08/21 08:56:14     1.3
+++ CentOS-Base.repo    2009/08/21 15:08:31
@@ -18,6 +18,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #released updates 
 [updates]
@@ -27,6 +28,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #packages used/produced in the build but not released
 [addons]
@@ -36,6 +38,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #additional packages that may be useful
 [extras]
@@ -45,6 +48,7 @@
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
 priority=1
+exclude=heartbeat-*
 
 #additional packages that extend functionality of existing packages
 [centosplus]

動作確認

# yum info heartbeat
...(略)...
Available Packages
Name       : heartbeat
Arch       : i386
Version    : 2.1.4
Release    : 9.el5
Size       : 1.6 M
Repo       : epel
Summary    : Heartbeat subsystem for High-Availability Linux
URL        : http://linux-ha.org/
License    : GPLv2 and LGPLv2+
...(略)...

epelのheartbeatを見つけられるようになりました。

2009-08-21

CentOSでheartbeatを使おうとしたがうまくいかず

2009-08-27追記: その後keepalivedに乗り換えました

CentOS-Testingからkeepalivedを入れてVRRPの実験に書きました。

選定理由

手元の本ではkeepalivedを使っていたので当初そちらにしようかと思いましたが、yum searchでは見つかりませんでした。調べてみると同等の機能としてheartbeatというパッケージがあるらしい。23. High Availability LVS: Failover protectionには以下のような説明がありました。

This is handled by having a redundant director available. Director failover is handled in the Ultra Monkey Project by heartbeat. Other code used for failover is vrrpd in keepalived.

Ultra Monkey Projectもyum searchでは見つからず、また調べてみるとheartbeat-ldirectordというパッケージで同等の機能が使えるっぽい。ということでこちらを試すことにしました。

セットアップ

以下のサイトを参考にしました。

$ sudo yum install ipvsadm heartbeat heartbeat-ldirectord

haclusterユーザが既に存在するという旨のエラーが出てheartbeatがインストールされないので、再度行う。

$ sudo yum install heartbeat

設定ファイル作成

/etc/ha.d/ha.cf

$ cd /etc/ha.d
$ sudo cp /usr/share/doc/heartbeat-2.1.3/ha.cf .
$ sudo vi ha.cf

変更内容

--- ha.cf       2009/08/21 10:57:54     1.1
+++ ha.cf       2009/08/21 11:42:22
@@ -49,7 +49,7 @@
 #
 #      keepalive: how long between heartbeats?
 #
-#keepalive 2
+keepalive 2
 #
 #      deadtime: how long-to-declare-host-dead?
 #
@@ -57,12 +57,12 @@
 #              split-brain (or cluster partition) problem.
 #              See the FAQ for how to use warntime to tune deadtime.
 #
-#deadtime 30
+deadtime 30
 #
 #      warntime: how long before issuing "late heartbeat" warning?
 #      See the FAQ for how to use warntime to tune deadtime.
 #
-#warntime 10
+warntime 10
 #
 #
 #      Very first dead time (initdead)
@@ -72,12 +72,12 @@
 #      we have a separate dead time for when things first come up.
 #      It should be at least twice the normal dead time.
 #
-#initdead 120
+initdead 120
 #
 #
 #      What UDP port to use for bcast/ucast communication?
 #
-#udpport       694
+udpport        694
 #
 #      Baud rate for serial ports...
 #
@@ -92,7 +92,7 @@
 #
 #      What interfaces to broadcast heartbeats over?
 #
-#bcast eth0            # Linux
+bcast  eth0            # Linux
 #bcast eth1 eth2       # Linux
 #bcast le0             # Solaris
 #bcast le1 le2         # Solaris
@@ -212,8 +212,8 @@
 #
 #      Tell what machines are in the cluster
 #      node    nodename ...    -- must match uname -n
-#node  ken3
-#node  kathy
+node   vm10
+#node  vm11
 #
 #      Less common options...
 #
@@ -255,6 +255,7 @@
 #
 #respawn userid /path/name/to/run
 #respawn hacluster /usr/lib/heartbeat/ipfail
+respawn root /usr/lib/heartbeat/pingd -m 100 -d 5s -a default_ping_set
 #
 #      Access control for client api
 #              default is no access
@@ -324,7 +325,7 @@
 #      more infomartion can be fould in http://www.linux-ha.org/ha_2ecf_2fUseLogdDirective
 #      Setting use_logd to "yes" is recommended
 #
-# use_logd yes/no
+use_logd yes
 #
 #      the interval we  reconnect to logging daemon if the previous connection failed
 #      default: 60 seconds
@@ -342,3 +343,5 @@
 #      will be compressed, the default is 2 (KB)
 #compression_threshold 2

+#      Enable cluster resource manager
+crm yes

なお、ja/pingd_ja: Linux HAによるとpingdはipfailにとって代わるコマンドらしい。

/etc/ha.d/logd.cf

$ sudo cp /usr/share/doc/heartbeat-2.1.3/logd.cf .
$ sudo vi logd.cf

変更内容

--- logd.cf     2009/08/21 11:45:09     1.1
+++ logd.cf     2009/08/21 11:45:46
@@ -1,18 +1,18 @@
 #      File to write debug messages to
 #      Default: /var/log/ha-debug
-#debugfile /var/log/ha-debug
+debugfile /var/log/ha-debug
 
 #
 #
 #      File to write other messages to
 #      Default: /var/log/ha-log
-#logfile       /var/log/ha-log
+logfile        /var/log/ha-log
 
 #
 #
 #      Facility to use for syslog()/logger 
 #      Default: daemon
-#logfacility   daemon
+logfacility    none
 
 
 #      Entity to be shown at beginning of a message

/etc/ha.d/authkeys

$ sudo cp /usr/share/doc/heartbeat-2.1.3/authkeys .
$ sudo chmod 600 /etc/ha.d/authkeys
$ sudo vi authkeys

変更内容

--- authkeys    2009/08/21 11:46:47     1.1
+++ authkeys    2009/08/21 11:47:40
@@ -20,7 +20,7 @@
 #      crc adds no security, except from packet corruption.
 #              Use only on physically secure networks.
 #
-#auth 1
-#1 crc
+auth 1
+1 crc
 #2 sha1 HI!
 #3 md5 Hello!

VMクローン

インストールや設定ファイルの変更をvm10と同様にvm11でも行うのは手間なので、vm10の1台でセットアップして、KVMのゲストOSイメージをコピーの手順でvm11を作り直しました。こっちのほうが楽です。

動作実験するも問題発生

サービス開始。2台で実行。

$ sudo /etc/init.d/heartbeat start

モニターしてみる。1台で実行。しかしエラー発生。

$ /usr/sbin/crm_mon -i 3
Defaulting to one-shot mode
You need to have curses available at compile time to enable console mode
Critical: Unable to connect to the CIB

調べてみると既知バグで0003226: heartbeat crm_mon not compiled with ncurses - CentOS Bug Trackerに登録されていました。

CentOSのyumレポジトリにrpmforgeを追加

yum-prioritiesを導入

AdditionalResources/Repositories/RPMForge - CentOS Wikiを参考にしました。

$ sudo yum install yum-priorities
$ sudo vi /etc/yum.repos.d/CentOS-Base.repo

変更内容

--- /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 08:48:25     1.1
+++ /etc/yum.repos.d/CentOS-Base.repo   2009/08/21 08:56:14     1.3
@@ -17,6 +17,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #released updates
 [updates]
@@ -25,6 +26,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #packages used/produced in the build but not released
 [addons]
@@ -33,6 +35,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/addons/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #additional packages that may be useful
 [extras]
@@ -41,6 +44,7 @@
 #baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=1

 #additional packages that extend functionality of existing packages
 [centosplus]
@@ -50,6 +54,7 @@
 gpgcheck=1
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=2

 #contrib - packages by Centos Users
 [contrib]
@@ -59,3 +64,4 @@
 gpgcheck=1
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
+priority=2

rpmforgeのセットアップ

$ wget http://apt.sw.be/redhat/el5/en/i386/RPMS.dag/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
$ sudo rpm --import http://dag.wieers.com/rpm/packages/RPM-GPG-KEY.dag.txt
$ rpm -K rpmforge-release-0.3.6-1.el5.rf.i386.rpm 
$ sudo rpm -i rpmforge-release-0.3.6-1.el5.rf.i386.rpm
$ sudo vi /etc/yum.repos.d/rpmforge.repo

変更内容

--- /etc/yum.repos.d/rpmforge.repo      2009/08/21 09:08:58     1.1
+++ /etc/yum.repos.d/rpmforge.repo      2009/08/21 09:09:11
@@ -9,3 +9,4 @@
 protect = 0
 gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
 gpgcheck = 1
+priority = 11

設定の確認

$ sudo yum check-update

rpmforgeの行が出ればOK。

virsh consoleを使うためにCentOSのシリアル端末を設定

CentOSのシリアル端末を設定

Setting up a serial console | HowtoForge - Linux Howtos and Tutorialsを参考にしました。

# vi /etc/inittab
S0:12345:respawn:/sbin/agetty ttyS0 115200 # この行を追加
1:2345:respawn:/sbin/mingetty tty1
# vi /etc/grub.conf
serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1 # この行を追加
terminal --timeout=5 serial console # この行を追加
title CentOS (2.6.18-128.4.1.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-128.4.1.el5 ro root=/dev/VolGroup00/LogVol00 console=tty0 console=ttyS0,115200n8 # console以降を追加
        initrd /initrd-2.6.18-128.4.1.el5.img

再起動すればシリアル端末が使えるようになります。

virsh consoleからの利用手順

まずゲストOSを起動します。

$ sudo virsh start vm10

ゲストOSが事前に起動済みの状態で、シリアル端末に接続します。

$ sudo virsh console vm10

シリアル端末から切断する方法はわかりませんでした。screenを使っていれば、別端末に切り替えてvirshのPIDを調べてkillするか、端末を切り替えずにscreenのkillコマンドでウィンドウごとkillすることができます。screenってほんと便利ですね。

kenyaさんからのコメントでCtrl+](右角括弧)で抜けられることを教わりました。これは便利です。

2009-08-20

virt-cloneでゲストOSイメージをコピー

コピー実行

以下のコマンドで起動します。

$ sudo virt-clone --original vm10 --name vm11 --file vm11.qcow2 --mac 52:54:00:12:34:57

設定変更

その後vm11を起動してホスト名、MACアドレス、IPアドレスを変更します。

ホスト名変更

# vi /etc/sysconfig/network
HOSTNAME=vm11 # この行を修正

さらに今すぐ変更するためにコマンドも実行します。

# hostname vm11

一旦ログアウトしてログインし直すとプロンプトも変わりました。

MACアドレス、IPアドレスを変更

# service network stop
# cd /etc/sysconfig/network-scripts
# ls ifcfg-eth0*
ifcfg-eth0  ifcfg-eth0.bak
# rm ifcfg-eth0
# mv ifcfg-eth0.bak ifcfg-eth0
# vi ifcfg-eth0
HWADDR=52:54:00:12:34:57 # この行と
IPADDR=192.168.11.242    # この行を修正
# service network start

設定変更用のスクリプト

毎回手動で上記の設定変更を行うのも面倒なので、シェルスクリプトを書いてみました。ゲストOSに入れておきます。

#!/bin/bash
if [ $EUID -ne 0 ]; then
    echo "This script must be run by root." 1>&2
    exit 1
fi

if [ $# -ne 1 ]; then
    echo "Usage: chgvm hostname" 1>&2
    exit 1
fi

hostname=$1

case $hostname in
vm10)
    ipaddr=192.168.11.241
    macaddr=52:54:00:12:34:56
    ;;
vm11)
    ipaddr=192.168.11.242
    macaddr=52:54:00:12:34:57
    ;;
*)
    echo "Wrong hostname: $1" 1>&2
    exit 1
esac

hostname $hostname
sed -i -e "s/^HOSTNAME=.*/HOSTNAME=$hostname/" /etc/sysconfig/network

service network stop

cat > /etc/sysconfig/network-scripts/ifcfg-eth0 <<EOF
# Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+
DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
HWADDR=$macaddr
NETMASK=255.255.255.0
IPADDR=$ipaddr
GATEWAY=192.168.11.1
TYPE=Ethernet
EOF

service network start

上記のvirt-cloneでコピーした後、以下のようにして変更します。

host$ sudo virsh start vm11
host$ sudo virsh console vm11
# ここでrootでログインして上記のシェルスクリプトを実行

virt-cloneした後はネットワークの設定がvm10と同一になっているので、まずvm11だけを起動してsshではなくconsoleからログインして、上記のシェルスクリプトで設定を変えるという手順をとる必要があります。

既存のKVMのゲストOSイメージをlibvirtに登録

手順

既存のKVMのゲストOSイメージをlibvirtに登録するのは、通常の手順としては用意されていないそうです。インストールに見せかけて即座に失敗するがエントリは作られるという方法で実現します。

ここでも--os-variant=centos5を試してみたのですがやはりエラーになってしまいました。

$ sudo virt-install -n vm10 -r 512 --vcpus=1 -f vm10.qcow2 -s 12 \
> --os-type linux --accelerate --network=bridge:br0 --hvm -c /dev/null --nographics -m 52:54:00:12:34:56 --os-variant=centos5
ERROR    OS variant 'centos5; does not exist in our dictionary for OS type 'linux'
Traceback (most recent call last):
  File "/usr/bin/virt-install", line 709, in 
    main()
  File "/usr/bin/virt-install", line 590, in main
    guest.set_os_variant(options.os_variant)
  File "/usr/lib/python2.6/dist-packages/virtinst/Guest.py", line 683, in set_os_variant
    {'var' : val, 'ty' : self._os_type}
ValueError: OS variant 'centos5; does not exist in our dictionary for OS type 'linux'

--os-variantをつけずに実行するとOKでした。

$ sudo virt-install -n vm10 -r 512 --vcpus=1 -f vm10.qcow2 -s 12 \
> --os-type linux --accelerate --network=bridge:br0 --hvm -c /dev/null --nographics -m 52:54:00:12:34:56

ここで別の端末でpsでプロセスIDを調べてkill -9します。

$ sudo virsh
virsh # destroy vm10
virsh # quit

-mで指定するMACアドレスは、一旦VMを起動してifconfigで調べておいたものです。virt-installの前にはシャットダウンしておきます。

man virt-installによるとXenの場合'00:16:3e'で始まる必要があり、QEMUの場合'54:52:00''52:54:00'で始まる必要があるそうです(2011-11-25追記: MACアドレスの値が間違っていました。タイプではなくコピペすべき>自分。←実はマニュアルが修正されていたようです。Bug 620838 – mistype in virt-install manpage - 54:52 should be 52:54)。 -mを指定しないとvirt-installがランダムに生成した値になりました(確か'00:16:3e'で始まっていました)。

この後確認すると/etc/libvirt/qemu/vm10.xmlという設定ファイルが作られていました。

参考にしたページ

KVMのゲストOSのネットワークをブリッジにする

Networking - KVMを参考にしました。

sudo kvm -hda vm10.qcow2 -m 256 -curses -net nic,00:23:7d:29:e1:02 -net tap,script=/etc/kvm/kvm-ifup

メモ

  • 00:23:7d:29:e1:02はランダムなMACアドレスです。ifconfigで表示された他のアドレスを変更してでっちあげました。
  • tunctlは無くてもいけました。ちなみにuml-utilitiesパッケージに含まれているらしい。
$ sudo aptitude show uml-utilities
Package: uml-utilities
State: not installed
Version: 20070815-1.1ubuntu2
Priority: extra
Section: universe/otherosfs
Maintainer: Ubuntu MOTU Developers 
Uncompressed Size: 336k
Depends: adduser, libc6 (>= 2.4), libfuse2 (>= 2.6), libncurses5 (>= 5.6+20071006-3), libreadline5 (>= 5.2), lsb-base (>= 3.0-10)
Suggests: user-mode-linux
Description: User-mode Linux (utility programs)
 User-mode Linux is a port of the Linux kernel to its own system call interface.  It provides a kind of virtual machine, which runs
 Linux as a user process under another Linux kernel.  This is useful for kernel development, sandboxing, jailing, experimentation,
 and many other things. 
 
 This package contains userspace utilities for use with User-mode Linux, including uml_mconsole, uml_moo, uml_switch, uml_net and
 tunctl.

Ubuntuでネットワークブリッジを作成

KVM Networking - Community Ubuntu Documentationを参考にしました。

bridge-utilsパッケージをインストールします。

$ sudo aptitude install bridge-utils

/etc/network/interfacesを以下のように書き換えます。

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
  address 192.168.11.102
  netmask 255.255.255.0
  gateway 192.168.11.1
  bridge_ports eth0
  bridge_stp off
  bridge_fd 0
  bridge_maxwait 0

で以下のコマンドを実行します。

$ sudo /etc/init.d/networking restart

libvirt: Wiki: Networkingによると/etc/sysctl.confも変更するらしいです。

$ sudo vi /etc/sysctl.conf

追加内容

net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

以下のコマンドを実行して変更を反映。

$ sudo sysctl -p /etc/sysctl.conf

KVMでCentOSをテキストモードでインストールする

KVMのインストール

基本的にはKVM Installation - Community Ubuntu Documentationに従って実行しました。

$ sudo apt-get install kvm libvirt-bin python-vm-builder qemu bridge-utils
$ sudo adduser $USER libvirtd

ゲストOS環境作成

以下のページを参考にしました。

うまく行かなかった手順

$ sudo aptitude install python-virtinst
$ qemu-img create -f qcow2 vm10.qcow2 10G
$ sudo virt-install --connect qemu:///system -n vm10 -r 512 --vcpus=1 -f vm10.qcow2 -s 12 \
  -c CentOS-5.3-i386-bin-DVD.iso --vnc --noautoconsole --os-type linux \
  --accelerate --network=bridge:br0 --hvm

シングルコアなのでvcpusは1に。上記の2つめの記事に従って--os-variant=は指定しない(man virt-installを見ると--os-variant=centos5でよさそうなのだがやってみるとうまくいかない)。インストールは始まるが、途中で"800 x 600 Graphic mode"と表示されてしまいだめだった。

さらに--nographicsオプションをつけて実行してみたが、途中で行頭に?が表示された状態でにっちもさっちもいかなくなった。

Shadows of epiphany » Blog Archive » How to run KVM without Xというページも見つけたがこれは試していない。

うまく行った手順

ググってみるとvirt-installerは使わずに直接KVMを使えばいけるらしい。あと、qemuとkvmはコマンドレベルで互換性があり、qemuと書く代わりにkvmと書けば動くそうだ。試したらそのままいけました。QemuやKVMのドキュメントやmanを見て以下のようにした。

$ qemu-img create -f qcow2 vm10.qcow2 10G
$ sudo kvm -hda vm10.qcow2 -cdrom CentOS-5.3-i386-bin-DVD.iso -boot d -m 256 -curses

大切なのは最初に"640 x 480 Graphic mode"と表示された時。見えないがこのタイミングでCentOS5インストール - CentOSで自宅サーバー構築の1枚目のスクリーンショットの画面が表示されている。単に<ENTER>を押すとGUIインストールが始まってしまうので、linux text<ENTER>と入力すること。

試した環境

ハードウェア
HP ML115G5
CPU
AMD Athlon 1640B (2.7GHz、L2 512KB、45W、AM2)
RAM
8GB
ホストOS
Ubuntu 9.04 server i386
$ uname -a
Linux sunshine12 2.6.28-15-server #49-Ubuntu SMP Tue Aug 18 19:30:06 UTC 2009 i686 GNU/Linux
$ dpkg -l | egrep '(kvm|libvirt-bin|python-vm-builder|qemu|bridge-utils)'
ii  bridge-utils                              1.4-5                             Utilities for configuring the Linux Ethernet
ii  kvm                                       1:84+dfsg-0ubuntu12.3             Full virtualization on i386 and amd64 hardwa
ii  libvirt-bin                               0.6.1-0ubuntu5.1                  the programs for the libvirt library
ii  python-vm-builder                         0.10-0ubuntu2                     VM builder
ii  qemu                                      0.10.0-1ubuntu1                   fast processor emulator

2009-08-14

WebWorkerの実行速度測定実験

実行結果

Safari 4.0.3

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; ja-jp) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=3.805
worker result=4999999950000000, elapsed=3.781
worker result=4999999950000000, elapsed=3.78
elapsedAverage=3.789

Chromium 4.0.202.0 r23297

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.202.0 Safari/532.0
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=1.734
worker result=4999999950000000, elapsed=1.652
worker result=4999999950000000, elapsed=1.658
elapsedAverage=1.681

Chrome 3.0.198.1

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.198 Safari/532.0
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=1.735
worker result=4999999950000000, elapsed=1.655
worker result=4999999950000000, elapsed=1.654
elapsedAverage=1.681

Firefox 3.5.2

userAgent=Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ja-JP-mac; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2
Start testing workers for 3 times. n=100000000
worker result=4999999950000000, elapsed=0.589
worker result=4999999950000000, elapsed=0.439
worker result=4999999950000000, elapsed=0.438
elapsedAverage=0.489

動作環境

機種 ID
MacBook5,1
プロセッサ名
Intel Core 2 Duo
プロセッサ速度
2 GHz

ソース

  • sum.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Web worker sample</title>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="stopwatch.js"></script>
    <script type="text/javascript">
    $(function() {
      var worker = new Worker("sum.js"),
        n = 100000000,
        tryCount = 3,
        tryIndex = 0,
        stopwatch = new Stopwatch();
     
      function log(message) {
        $('#result').append(message + '<br>');
      }
      log('userAgent=' + navigator.userAgent);
      log('Start testing workers for ' + tryCount + ' times. n=' + n);
      
      worker.onmessage = function(event) {
        stopwatch.stop(); 
        log('worker result=' + event.data + ', elapsed=' + stopwatch.elapsedTime());
        if (++tryIndex < tryCount) {
          startTry();
        }
        else {
          log('elapsedAverage=' + stopwatch.elapsedTimeAverage().toFixed(3));
        }
      }
      worker.onerror = function(event) {
        log("worker error: " + event.data);
      }
    
      function startTry() {
        stopwatch.start();
        worker.postMessage('' + n);
      }
      startTry();
    });
    </script>
    </head>
    <body>
    <div id="result"></div>
    </body>
    </html>
    
  • sum.js
    onmessage = function(event) {
      var n = parseInt(event.data);
      var sum = 0;
      for (var i = 0; i < n; i++) {
        sum += i; 
      }
      postMessage('' + sum);
    }
    
  • stopwatch.js
    function Stopwatch() {
      this.elapsedTimes = [];
    } 
      
    Stopwatch.prototype.start = function() {
      this.startTime = new Date();
    } 
    
    Stopwatch.prototype.stop = function() {
      this.stopTime = new Date();
      var time = (this.stopTime.getTime() - this.startTime.getTime()) / 1000;
      this.elapsedTimes.push(time);
    }
    
    Stopwatch.prototype.elapsedTime = function() {
      return this.elapsedTimes[this.elapsedTimes.length - 1];
    }
    
    Stopwatch.prototype.elapsedTimeAverage = function() {
      var n = this.elapsedTimes.length,
        total = 0;
      for (var i = 0; i < n; i++) {
        total += this.elapsedTimes[i];
      }
      return total / n;
    }
    

2009-07-30

90度単位ではない回転テキストのサンプル

できたことはできましたが、IEのはビットマップイメージを回転しているのでがたがたになってしまいました。

参考: DXImageTransform.Microsoft.Matrix

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Text rotation</title>
<style type="text/css">
.example-date {
  position: relative;
  font-family: Helvetica, Arial;
}
.day {
  position: absolute;
  top: 0;
  left: 0;
  font-size: 32pt;
}
.month {
  position: absolute;
  top: 32pt;
  left: 0;
  font-size: 18pt;
}
.year {
  position: absolute;
  top: 10pt;
  left: 32pt;
  font-size: 12pt;
  display: block;
  -webkit-transform: rotate(-30deg); 
}
.year, x:-moz-broken {
  position: absolute;
  top: 8pt;
  left: 32pt;
  font-size: 12pt;
  -moz-transform: rotate(-30deg); 
}
</style>
<!--[if IE]>
<style type="text/css">
.year {
  filter:progid:DXImageTransform.Microsoft.Matrix(
  M11=0.866,
  M12=0.5,
  M21=-0.5,
  M22=0.866,
  Dx=1.0,
  Dy=1.0,
  FilterType='bilinear',
  sizingMethod='auto expand'
  );
  top: 4pt;
  left: 32pt;
}
</style>
<![endif]-->
</head>
<body>
  <div class="example-date">
    <span class="day">31</span> 
    <span class="month">JULY</span> 
    <span class="year">2009</span>
  </div>
</body>
</html>

2009-07-29

text rotation with css

Text Rotation with CSSを読んで試してみた。いつか使う時が来るかもということでメモ。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Text rotation</title>
<style type="text/css">
.example-date {
  position: relative;
  font-family: Helvetica, Arial;
}
.day {
  position: absolute;
  top: 0;
  left: 0;
  font-size: 32pt;
}
.month {
  position: absolute;
  top: 32pt;
  left: 0;
  font-size: 18pt;
}
.year {
  position: absolute;
  top: 10pt;
  left: 28pt;
  font-size: 12pt;
  display: block;
  -webkit-transform: rotate(-90deg); 
}
.year, x:-moz-broken {
  position: absolute;
  top: 8pt;
  left: 28pt;
  font-size: 12pt;
  -moz-transform: rotate(-90deg); 
}
</style>
<!--[if IE]>
<style type="text/css">
.year {
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  top: 4pt;
  left: 32pt;
}
</style>
<![endif]-->
</head>
<body>
  <div class="example-date">
    <span class="day">31</span> 
    <span class="month">JULY</span> 
    <span class="year">2009</span>
  </div>
</body>
</html>

回転できるのはいいんだけど、FirefoxとWebkit (SafariとChrome)では位置がずれるのでCSSハックで調整が必要だった。試したのはMac OS X Leopard上のSafari 4.0.2とChrome 3.0.195.1 (開発版)とWindows 7RC上のIE 8.0.7100.0です。

また、記事の通りWindows7+IE8では回転はできるがアンチエイリアシングはかからなくなってしまうことを確認。

2009-07-04

Checkstyle用カスタムチェックの作成

例としてreturnの値を括弧で囲んでいないか(*)のチェックを行うモジュールを作成してみました。

(*): Code Conventions for the Java(TM) Programming Language: Contentsreturn Statements参照

参考URL
Checkstyle - Writing Checks
成果物
mycheckstyleexperiments

Firefoxでリロードボタンとストップボタンを統合する

userchrome.css - Mozilla Firefox まとめサイト

Firefox 3.5でもできました。デフォルトではリロードボタンの右にストップボタンがあるのでまず入れ替えてからuserChrome.cssに以下の内容を追加してFirefoxを再起動すればOKです。

/*
 * リロードボタンとストップボタンを統合。
 * ストップボタンの右にリロードボタンがあることが前提。
 */
#stop-button:not([disabled=true]) + #reload-button,
#stop-button[disabled=true]
{
    display:none !important;
}

2009-01-20

Linux Virtual Server (LVS)



[24時間365日] サーバ/インフラを支える技術 ?スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ)を見ながら、まずは仮想IPアドレスを追加してみた。[24時間365日] サーバ/インフラを支える技術 ?スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ)


その後send_arpコマンドを試そうと思ったが、見当たらない。本はdebianが対象なのでCentOSだと違うようだ。ググってみるとLinux Virtual Server Administrationというのを発見。まずはじっくり読んでみよう。





ProLiant ML115 G5をもう1台購入



NEC Express 5800 S70/SDにするか悩んだがNTT-X Storeでは入荷後数十分で完売になってしまうし、サーバーの勉強という意味ではIPMIなどが使えるこっちだよなってことで購入。今回は4000円引きでした。


購入費用は






PCHP-ProLiant-ML115 G5¥12,170NTT-X Store
RAMSILICON POWER SP004GBLRU800S22 2GBx2¥3,480パソコンハウス東映
 合計¥15,650 


これで2台体制になったので、サービス稼動を維持しつつ、カーネルアップデートと再起動を1台ずつ行う方法を勉強したいところ(←というぐらいしか2台目を買う大義名分がなかったりして)。OpenVZとかでやればいいという話もあるんですが、物理的な2台で実験して安心したいというのとまず現実環境でできるようになってからでないと仮想環境でうまくいかないときによくわからないというのはあるので、2台体制にする意義はあるはずです。


まずは仮想IPアドレスを引き継ぐという基本的なところからじっくり練習する予定。





2009-01-15

ProLiant ML115 G5にWindows XPを入れた



前回うまくいかず断念していたが再挑戦してできたっぽい(今リブートしてインストール続行中)。


以下のページを参考にしました。感謝感謝。



入れるドライバは


hp鯖-ProLiant-ML115(格安Server)/Windows2000 - wiki@nothing


を参考にしましたが、HPのページから最新を探して取得しました。


あと、本体付属のEASY SETUP CDで起動して本体の情報も見てみて、HP-ProLiant-ML115 G5まとめwiki - 仕様・比較と照らして確認してみました。



  • チップセット

    • nVidia Corporation MCP55



  • VGA

    • Matrox Graphics, inc. MGA G200e [Pilot] ServerEngines (SEP1)



  • NIC

    • NC105i PCIe Gigabit Ethernet Server Adapter




HP Support & Driversで"ML115 G5"で検索して"Download drivers and software" -> "Microsoft Windows Server 2003"とたどり、


HP ProLiant ML115 G5 Server series -  Download drivers and software - HP Business Support Center


のページから必要そうなものを入れました。日本語版があるドライバは日本語版を選択し、チップセットとグラフィクスドライバは英語版しかなかったので英語版にしました。



nLiteでドライバを統合するときは、THE MAD RADEON BLOGGERS: nLiteでnF4のnVRAIDドライバを統合するのとおりsataraidフォルダは「Textmodeドライバ」でsata_ideフォルダは「通常PNPドライバ」を選択。


で、nLiteでISOイメージを作ってDVD-RWに書き出してインストール。ところが、途中で"Line XXXXX of the INF file \i386\txtsetup.inf is invalid"と言われてインストール失敗。作業ディレクトリ内のi386\txtsetup.infの該当箇所を見てみると、["Keyboard Layout"]セクションの各行の右辺がダブルクォーテーションで囲まれている行と囲まれていない行がありどうも囲まれていないのがまずいようだ。というのも元のXP SP2のCDでは全ての行が囲まれていたので。で、囲むように修正してISOイメージを作り直してDVD-RWに書き出して(RWにしておいたので気軽に修正出来てよかった)、再度インストールを試すと今度はうまくいきました。





2009-01-14

ProLiant ML115 G5にWindows 7 betaを入れてみた



本当は先にWindows XPを入れようと思ってnLiteを使ってドライバを統合したインストールCD-ROMを作って試したが起動後すぐ画面が真っ黒になってしまい、インストールできませんでした。なぜかCTRL+ALT+DELETEだけは効くんだけど。メモリが4GBなのがまずいのかと2GBにしてみたり、付属のキーボードとマウスをやめてUSBキーボードとUSBマウスで試したりしたけど全滅。


というわけで先にWindows 7 betaを試してみました。こちらはわりとあっさり。ただ、インストーラ中は付属キーボードは効いたけど付属マウスは反応しなかったのでUSBマウスにしました。それ以外は何も気にせずインストールできました。マウスが効かないと思ったのは勘違いでした。いまどき光学じゃないマウスでしかも異様に転がらないだけでした。パーティションはまっさらの状態からWindows 7のインストーラ上で作成したのですが、Windowsが必要に応じて作るととメッセージボックスが出たと思ったら、最初のバーティションとして200MB勝手に作られて自分で指定した30GBはその次のパーティションになっていました。


その後、gparted-live-0.4.1-2.isoでブートしてパーティションを全削除後、プライマリパーティションを1つだけ作成してタイプをNTFSにし、Windows 7 betaのCDで起動してフォーマットしてインストールするという手順を試すと、さすがにこの場合は勝手にパーティションを追加したりはしませんでした。





ブログ アーカイブ