iPXEでサーバの機器情報を取得する。

新しい機器をラックマウントする際には、納品時にメーカー、型番、シリアル番号を控え、ラック位置、棚位置とひもづける必要があると思います。この手の管理作業は台数が増えるほど手間が増えるので手作業ではやりたくないことの一つです。どの型番のどのスペックの機器にどのOSをインストールするか、という観点ではシリアル番号での識別が必要です。実際にPXEブートでOSをインストールするには、シリアル番号に紐づいたMACアドレスを指定してやる必要があります。MACアドレスを指定するためにMACアドレスを控えるにはBIOSの設定画面などからMACアドレスを確認し控えるというアナログなことをやるかもしれませんが、これは怠惰な我々にとっては面倒過ぎて死ねますね。

PXEブートを使っている場合、iPXEを使うとこの面倒な作業をなくすことができます。PXEブートでインストールするには、通常はDHCPでIPアドレスを割り当て、TFTPサーバからブートイメージをダウンロードし、PreseedやKickstartなどでOSをインストールすると思います。DHCP/TFTPサーバとしてdnsmasqを使用していることを前提とすると、OSのインストール用のイメージをダウンロードさせるにはdnsmasqでMACアドレスが登録されていることを必要条件とします。一方、MACアドレスが未登録の場合にはiPXEを使うようにしてやれば、機器情報を取得することができます。

iPXEスクリプトで取得できる情報。

ハードウェアの構成情報として、資産管理の観点も含めて必要な情報としては、シリアル番号、MACアドレス、メーカー、機器タイプでしょう。最低限シリアル番号とMACアドレスがあれば問題ないかもしれませんが、シリアル番号をキーにして別でメーカー、機器タイプを記述した管理表を作るのも面倒です。これらの情報を取得するには、次のようなiPXEスクリプトを用意します。

#!ipxe

dhcp
chain http://${next-server}:9393/inventory/${serial:uristring}/${mac}/${manufacturer:uristring}/${product:uristring}

chainで渡されたURL の各パラメータは次の通りです。iPXEクライアントである各マシンの情報がこのパラメータに埋め込まれた形で、各マシンから${next-server}で指定されたWebサーバ(TFTPサーバ)にアクセスされます。

  • ${serial:urlstring}:シリアル番号(string), 21byte

  • ${mac}:MACアドレス(hex)

  • ${manufacturer:uristring}:メーカー(string), 33byte

  • ${product:uristring}:機器型番(string), 31byte

string型のパラメータはそれぞれ固定長なので例えば次のようなコードでログに出力すると

f.puts "#{Time.now} SN: #{params[:sn]} MAC: #{params[:mac]} Manu: #{params[:manufacturer]} prod: #{params[:product]}"

下記のように余計な空白が残ります。

Thu Apr 05 17:24:59 +0900 2012 SN: MA6S000000           MAC: 00:26:2d:01:01:01 Manu: FUJITSU-SV                       prod: PRIMERGY RX200 S6

不要な半角空白文字は次のようにトリミングしてやれば良いでしょう。

sn = params[:sn].gsub(/\s+$/, '')
mac = params[:mac].gsub(/\s+/, '')
manufacturer = params[:manufacturer].gsub(/\s+$/, '')
product = params[:product].gsub(/\s+$/, '')
Fri Apr 06 18:37:27 +0900 2012 SN: MA6S000000 MAC: 00:26:2d:01:01:01

なお、iPXEスクリプトのその他の設定項目については Upstreamのドキュメント を参照ください。

iPXEスクリプトに誘導する。

iPXEスクリプトをロードさせるには、DHCPでIPアドレスを割り当て、TFTPサーバからiPXE用のブートイメージをダウンロードできるようにします。dnsmasqを使う場合、下記のように設定します。

enable-tftp
tftp-root=/var/lib/pxelerator/tftpboot
dhcp-boot=net:#known,undionly.kpxe
dhcp-match=gpxe,175   # gPXE sends a 175 option.
dhcp-boot=net:gpxe,http://${next-server}:9393/SNreg.ipxe

各項目は次の通りです。

最新バージョンのdnsmasqでは下記のように設定するのが良いでしょう。 2

enable-tftp
tftp-root=/var/lib/pxelerator/tftpboot
dhcp-boot=tag:!known,undionly.kpxe
dhcp-match=set:gpxe,175   # gPXE sends a 175 option.
dhcp-boot=tag:gpxe,http://${next-server}:9393/SNreg.ipxe

iPXEスクリプトでchainで渡されたURLには、は何らかのWebアプリケーションサーバで処理すれば良いでしょう。自分たちの環境では t9mdさん が開発した pxelerator というリモートインストールツールの中でこれらの仕組みを使っており、パラメータの処理はRubyの軽量WebフレームワークSinatraで行っています。 3

最低限必要な作業。

シリアル番号、MACアドレス、メーカー、機器タイプは取得できるようになりました。ラック位置、棚位置は別の方法で取得する必要があります。これは、例えばラック位置や棚位置によって使用するスイッチ、スイッチポートをルールづけしておけば、スイッチで接続している対向機器のMACアドレスを収集すればMACアドレスをキーにして先ほどの情報と突合せできるでしょう。また、ラックマウントでの物理作業を除くと、最低限シリアル番号は控えておく必要があります。これらを取得できれば、rackdiagなどを使えばラック構成図の自動生成もできなくはないでしょう。

しかしこれでもまだ機器毎に任意のOSをインストールすることはできません。そこでpxeleratorのような自動インストール管理ツールの出番です。pxeleratorではMACアドレスが分かればインストールする機器毎にPXEブートでTFTPで渡すbootmenuとKickStartファイルを動的に渡すことができます。MACアドレス毎にインストールの許可不許可を与えるためにMACアドレスとホスト名の対を記述しファイルをdhcp-hostsfileで指定しています。このファイルへのMACアドレスの自動登録の話を次回行う予定です。

1

現在はUbuntu 10.04 LTSを使用しており、このdnsmasqのバージョンは2.52なのでちょうど古い設定方法なのですね。

2

下位互換の関係で古い形式でも大丈夫です。

3

Githubで公開されているのはかなり初期のバージョンなので今とだいぶ違いますし、今回の話の機能はもちろんありません。

一ヶ月検診、そして風邪をひいていた事実。

今日はおまめちゃんの一ヶ月検診でした。身長は56.4cm, 体重は4,640gでした。誕生時からそれぞれ+4.4cm, +926gの増加です。順調に育っているのですが、髪の毛の伸び具合は、同時期に生まれた子よりも遅いみたいです。女の子なのに…。ヨメさんが髪の毛伸びるのが遅いらしいので、そこは母親になのかもしれません。どっちに似ている、といえば低気圧で体調が悪くなるのはワシに似てしまったのか、昨日の春の嵐の前日の一昨日にめっちゃグズっていたらしく、低気圧になってしまった昨日は割とおとなしかったとのこと。似てほしくない変なところばかり、親に似てしまうとは…。

http://distilleryimage9.instagram.com/b3d78edc7e4811e18bb812313804a181_7.jpg

似てほしくないといえば、今日の一ヶ月検診でおまめちゃんは風邪をひいていると診断されてしまいました。そしてワシも今朝渋谷駅降りて改札駅を出たあたりからめまいがして、一日ダルい感じ。そんなところも似てしまったのか、と思ったのですが、おまめちゃんは先週の土曜あたりから泣き声がハスキーボイスになっているので、おまめちゃんが先に風邪ひいて、それをワシがもらったのかもしれません。が、ヨメさんには、ワシの場合は休んでないし疲れがたまっているだけでしょ、と言われました。

おまめちゃんと一緒に今日は早く寝ることにします…。

tinkererでblockdiagを使う。

tinkererはSphinxを使っているので、blockdiagを組み込むのも簡単です。 blockdiagの公式ドキュメント にあるとおり、conf.pyのextensionsに shinxcontrib.blockdiag を追記し、blockdiag_fontpathでフォントパスを指定します。

diff --git a/conf.py b/conf.py
index e1fab6c..9e5a79f 100644
--- a/conf.py
+++ b/conf.py
@@ -47,7 +47,7 @@ rss_service = None
 # **************************************************************

 # Add other Sphinx extensions here
-extensions = ['tinkerer.ext.blog', 'tinkerer.ext.disqus']
+extensions = ['tinkerer.ext.blog', 'tinkerer.ext.disqus', 'sphinxcontrib.blockdiag']

 # Add other template paths here
 templates_path = ['_templates']
@@ -66,6 +66,8 @@ html_sidebars = {
     "**": ["recent.html", "searchbox.html"]
 }

+blockdiag_fontpath = '/usr/share/fonts/truetype/vlgothic/VL-PGothic-Regular.ttf'
+
 # **************************************************************
 # Do not modify below lines as the values are required by
 # Tinkerer to play nice with Sphinx

あとは、tinkerコマンドでブログ用のreSTファイルを生成し、

$ tinker -p 235959
New post created as '/home/user/blog/2012/04/03/235959.rst'

blockdiagのコードを記述します。試しに公式ドキュメントにあるサンプルを記載してみました。

Name

Description

A

browsers in each client

B

web server

C

database server

最後にtinkerコマンドでビルドすれば完了です。

$ tinker -b -q

1ヶ月経ちました。

世の中はエイプリルフールネタで今年も盛り上がっていたみたいですが、我が家では今日でちょうどおまめちゃんが生まれて一ヶ月記念で盛り上がっていました。午前中はワシが家の掃除をしている間、ヨメさんと一緒にヨメさんの実家に行き、遊びに来ていたヨメさんの親戚に可愛がられていたようです。夕方にはワシの母が、妹のお宮参り&七五三のときに使った着物を持ってきてくれたので、記念写真を撮りました。今週末には親子3人で近所の氏神様にお参り行って、親を交えたお宮参りはもう少し暖かくなってから実家の近くの神社に行く予定です。

../../../_images/omame-20120401.jpg ../../../_images/omame-20120401-kimono.jpg

GEEK DAY TOKYOに参加しました。

前職で一緒に働いていた nittyan に何か発表してほしいと依頼されたので、 GEEK DAY TOKYO でネタを発表してきました。 “こまちゃん監視システムをPicasaからCouchDBに切り替えた。” のような軽めの内容でということだったのですが、1週間くらい前まで何も考えていませんでした。おまめちゃんで手一杯だったのが正直なところです。で以前からブログの移行を考えていたことや、3月にはてブのトラッキング情報取得の騒動と、4/1の前日ということでちょうど良いタイミングだな、ということではてなダイアリーからの移行についてをネタにしました。発表の資料は slideshare に公開してあります。ヨメさんの用事や車の6ヶ月点検が終わってから夕方からの参加でした。いつも参加している勉強会とはちょっと趣きも、発表内容の対象も異なる勉強会で、印象的にはOSCの懇親会でのLTみたいな感じでした。ここ数年懇親会参加してませんけど。:p

移行の技術的な理由は資料に書いてありますので、ここではGithubで公開した 移行ツール についての補足をしておきます。使い方は README.md に記載してあるので、ここでは書いていないことをば。Movable Type形式のエクスポートデータを入力ファイルにしてmt2rest.pyを実行すると、カレントディレクトリ下にoutディレクトリを作成し、その下にtinkererで生成するYYYY/MM/DD形式でのディレクトリを作ります。そしてその下に、はてなダイアリーでのエントリ毎( ‘*’ 一つで始まるエントリ)にreSTファイルを生成します。tinkererではreSTファイルのファイル名は、 tinkerer -p POST のように -p オプションで指定したブログタイトルがファイル名 title.rst のようになりますが、そのままブログのタイトルを使ってしまうと、ファイル名が日本語名になってしまうので不都合です。なので、エントリの公開時間を使い、 HHMMDD.rst となるようにしています。このエントリの名前は、master.rst.tmpに、最新の日付が上になるようにソートして記述しています。master.rstの並び順は、ブログでの表示順に影響します。一度生成したoutディレクトリ以下のreSTファイルを使って、tinkerコマンドでHTMLを生成すると、最初の一回だけRSSが生成されますが、その後reSTファイルを編集してHTMLを再発行してもRSSには再発行されません。現状、mt2rest.pyでは部分的にできていないことがありますが、機能実装後やバグ修正後にmt2rest.pyでreSTファイルを再生成し、HTMLを再発行してもRSSは再発行されませんので、エクスポートデータだけ保存しておけば、機能未実装分で意図通りに表示されない項目があっても個別に手で編集しなおす必要はありません。

なお、GEEK DAY TOKYOで発表後に、画像が表示されない件については既に修正済みです。まだ未実装部分やバグがあるので、はてなダイアリーからの移行を考えている方は、バグ報告及びパッチプリーズ。