2009年11月2日月曜日

無料素材

「写メ de 新聞」サービスを作るにあたって、利用した無料のサービスを紹介します。
これがなければ、もっとしょぼいデザインになるところでした。

「携帯サイト簡単構築」携帯サイトのテンプレート
携帯サイトを作るのは初めてだったので、通常のPCブラウザ用のHTMLとはいろいろな面で異なる事が多いです。携帯サイト用のテンプレートもいろいろ世の中に存在しているのですが、ここのテンプレートはシンプルなのと三つのキャリアで共通で使えるところが気に入りました。
http://web.rejec.net/

「Open Source Web Design」PCサイトのテンプレート
アメリカのサイトですが、そのまま使えるクールなテンプレートが2,000個以上も用意されています。ぱらぱらとたどっていけば、きっと気に入るテンプレートが見つかります。今回は割とシンプルなテンプレートを入手しました。中身のHTMLが想像以上にシンプルだったので、動的コンテンツを利用するサイトでも大変使いやすいです。
http://www.oswd.org/

「Interspire」ロゴのデザイン
いろんなテンプレートがあるようですが、Resouces - Website Templatesを選択して、さらにLogo Designsを選択すると、かっこいいアイコン付きのロゴデザインが用意されています。ロゴの文字は入っていないですが、Illustratorファイルとしてダウンロードできます。Illustrator(自分のように貧乏な人はInkscape)を用意すれば、文字を編集する事ができます。なかなかおすすめです。
http://www.interspire.com/

「FavIcon from Pics」favicon画像の作成
faviconとは、ブラウザのアドレスバーの左側やブックマークの一覧などで使われる、ちっちゃな画像です。意外と作るためにはツールなどが必要で、かつそれはWindows用が多いのでにわかマカーは一苦労です。それでもこのサイトを使えば、大きめの画像をアップロードするだけでちっちゃなfaviconを返してくれます。
http://www.html-kit.com/favicon/

α版公開

初めてのPython & Google App Engineで作成したアプリを、ようやく公開しました。
とにかく世に出して、意見を問おうかと考えています。

「写メ de 新聞」
http://shamedeshimbun.appspot.com/pc/

「写メ de 新聞」は、写メールを使って新聞を作れるサービスです。 記事の投稿はとても簡単。携帯で撮った写真に記事をつけて、あらかじめ用意されたアドレスに写メールで送るだけです。 送った写メールは、速報としてすぐに携帯やPC上で配信されます。 一通り記事がそろったら、PDFでまるで本物のような新聞を作成する事もできます(作成予定)

仲間内でのゴルフコンペや旅行などみんなが集まるときは、「写メ de 新聞」でみんなの新聞を作ってください!

2009年11月1日日曜日

捕捉仕切れなかった実行時例外をログに出力する

RequestHandlerは、実行例外が処理されなかった時に、最後にexception_handlerメソッドを実行する。
ここに、例外の情報を出力するロジックと、共通のエラー画面を表示するロジックを記述するとよい。
例外の情報は、traceback.format_exc()を使うと簡単だ。

# importは省略

class BaseRequestHandler(webapp.RequestHandler):
def handle_exception(self, exception, debug_mode):
logging.error(traceback.format_exc())
self.response.out.write('エラーが発生しました')

2009年10月27日火曜日

メールに添付されているファイルを取得する

ちょい苦労したけど、これで行けそう。

class MailHandler(InboundEmailHandler):
def receive(self, message):
attachment = message.attachments # ここ注意
binarydata = message.[1].payload.decode(message[1].encode)

でもこれは、添付ファイルが一つの場合のみ。
添付ファイルが一つの時は、message.attachmentsはtupleで(添付ファイル名, EncodePayloadオブジェクト)
となっている。
添付ファイルが二つの時は、message.attachmentsはlistで、[(添付ファイル名, EncodePayloadオブジェクト), (...)]となっている。
さらに添付ファイルがない時には、messageにattachmentsがそもそも存在しない。
それも踏まえて、場合分けをする必要があるようだ。

http://groups.google.com/group/google-appengine/browse_thread/thread/8bf0ab058eb3fcb3/dc447ee56ef59890?lnk=raot

2009年10月25日日曜日

GAEで受信したメールの件名を取得する

これでいけるようだ。

class MailHandler(InboundEmailHandler):
def receive(self, message):
header = decode_header(message.subject)
subject = ''
for s, charset in header:
if charset:
subject += unicode(s, charset)
else:
subject += s

無条件でunicode(s, charset)とやってしまうと、件名が英語だけの時にcharsetがNoneになる事があるので注意しよう。

Google App Engineでメール受信できた人いる?

Google App Engine 1.2.6からメールを受信する機能が追加された。
これは便利だと早速試してみたけれども、なかなかうまく行かない。
ネットで調べてみても、「できるようになったらしいよ」とGoogleやGIGAZINEのニュースを引く人はいるけれども、実際に受信したとかあるいはいろいろトラブったという話は、ヒットしない。Googleのサイトも英語は説明あるけど日本語の説明がないのもちと怪しい。

とにかく、今の事象を書いておくとする。だれか助けて。

[開発サーバでの話]
app.yamlに以下の設定をする。

- url: /_ah/mail/.+
script: main.py
login: admin

そして管理コンソールからメールを送ると、次のメッセージが出る。
Message send failure
Current logged in user is not authorized to view this page

まあ、(login:adminとしているので)そりゃそうなんだけど、じゃあどうしろと?


[本番サーバでの話]
駄目もとでデプロイして、regist@appid.appspotmail.com宛にメールを送ると、こんなつれない返事が返ってくる。
��ちなみにappidは、"http://appid.appspot.com/"のappidと合わせてあります)

This is an automatically generated Delivery Status Notification

Delivery to the following recipient failed permanently:

regist@appid.appspotmail.com

----- Original message -----
��以下略)



理由半分くらい判明
開発サーバでlogin:adminで入れないのは、まあしょうがないみたい。
本番サーバでうまく行かなかったのは、app.yamlに次の設定を入れていなかったから。
inbound_services:
- mail
最初は入れていたんだけど、ソースを編集しているときに削除されてしまったみたい。
これがなくても開発サーバの管理コンソールからメールが送れてしまったのが、原因発見が遅れた原因。
無事googleさまからメールが届いて一安心。

2009年10月19日月曜日

smtp2webをMac OS X(10.5)で動かす

GAEではメールを受信するアプリを作るときには、smtp2webを使う必要があるけれども、いちいちサーバにデプロイしないとテストができない。非常に不便なので、何とかmac上でローカルにsmtp2webをサービスとして起動できないかどうか確認する。

1. smtp2webのインストール
smtp2webのソースコードは公開されているので、subversionを使ってチェックアウトする。
チェックアウトフォルダは、とりあえずログインしているユーザーの書類フォルダに展開。

2. smtp2webの起動
そのままだとsmtp2webは動かない。server/smtpserver.tacファイルの修正が必要。具体的には-uにroot、-gにdaemonを指定する。
runserver.shファイルがあるフォルダに移動して、sudoコマンドを使ってrunserver.shを起動する。

3. (以下作成中)

GAEが1.2.6からメール受信機能を用意したので、smtp2webは使用しない事にした。
そのため、調査も終了〜。

2009年10月12日月曜日

PILをMac OS 10.5 (Leopard)に入れる

Google App Engineでは、画像処理を行うためのサービスが提供されている。
このサービスをローカルでも使うためには、MacにPILをインストールする必要がある。
http://code.google.com/intl/ja/appengine/docs/python/images/overview.html#Development_Server

このPILをMac OS 10.5に入れるに大変だったので、備忘録として記述。

1. PILのインストール
dmgファイルをダウンロードしてインストールしようとすると、途中でインストーラーが「このディクスにはpythonが入っていない」という警告を出して、次に進めなくなる。これは、dmgの代わりにソースをダウンロードして、コマンドラインからインストールするのがよいようだ。

Finder -> アプリケーション -> ユーティリティ -> ターミナル
$cd (ダウンロードしたtar.gzファイルを展開したディレクトリ。"setup.py"ファイルがあるはず)
$sudo python setup.py install

2. JPEGデコーダーのインストール
PILをインストールしても、JPEG画像を操作しようとすると次のエラーが発生する事がある。
IOError: decoder jpeg not available
このときは、JPEGデコーダーを追加でインストールする。

http://www.ijg.org/
jpegsrc.v7.tar.gzファイルをダウンロードして、展開する
Finder -> アプリケーション -> ユーティリティ -> ターミナル
$cd (展開したディレクトリ。install.txtがあるはず)
./configure
make
make test
sudo make install

このあと、1.をもう一度行う。
そのとき1.のディレクトリにあるbuildディレクトリを削除しておく
sudo rm -fr build

djangoテンプレートで日本語が文字化けする

utf-8で保存された文字列をsjisで定義されたdjangoのテンプレートで表示すると、日本語が化けます。
このときは、djangoのカスタムフィルターを用意して、utf-8をsjisに変換します。

[customfilters.py (utf-8 -> sjis変換をするフィルターを定義する)]
from google.appengine.ext import webapp

register = webapp.template.create_template_register()

@register.filter
def sjis(value):
return value.encode('sjis')

[main.py (テンプレートを出力するロジックのあるモジュール)]
webapp.template.register_template_library('customfilters')

[template.html]
{{ myValue|sjis }}


参考
http://kaihatsu.mikagamikobo.com/2009/09/google-app-engine-1.html

2009年10月8日木曜日

reportlabは1.2系では動かない

Google App EngineでPDFを出力するには、reportlabを使うとよいと書かれている。
しかしこのreportlab、ローカルのSDKではバージョンが1.2になると以下のエラーが発生する。

: 'HardenedModulesHook' object has no attribute '_files'

対応方法は、以下のURLから1.9をダウンロードしてアプリケーションに上書きすること。

「Google App Engine プロジェクト ホームページ」
http://code.google.com/p/googleappengine/downloads/list
※検索条件で「All donwloads」を選択する

ちなみに、本番環境ではSDKの環境に関係なくreportlabでPDFを生成できました。



1.2.7では動きました(^^)V

やっぱり駄目でした。具体的には、
1. ソースコードをlatin-1で保存して実行すると、実行できる。
2. ソースコードをutf-8で再保存して実行すると、上記のエラーが発生する
3. ソースコードをlatin-1にもどしても、やはりエラーが発生する
4. アプリケーションの.pycファイルを削除すると、実行できる(1.の状態に戻る)
です。
どうやら、pythonで鬼門のエンコード周りでどこかに不具合があるようです。
ちなみにサーバにデプロイするか、1.1.9にバージョンダウンするとうまく動くという事は、1.2.X系のGAEのSDKに問題がありそう...

2009年10月4日日曜日

静的ファイルを公開する

Google App Engineで言語がpythonのときに、静的なファイルを公開する方法。

1. 公開したいファイルを用意する。このときURLとファイル名は異なっていてもよい。
2. app.yamlのhandlersに次のエントリを用意する
- url: 静的ファイルをリクエストするURL
static_files: 用意した静的ファイルのパス
upload: 用意した静的ファイルのパス

例:http://foo.bar.com/hoge.htmlを公開する。

/static/hogeimpl.htmlファイルを用意する
- url: /hoge.html
static_files: static/hogeimpl.html
upload: static/hogeimpl.html

smtp2webがらみで使えるネタです。
この内容は、用途は違いますがGAEの一般的な質問に載っていました。
http://code.google.com/intl/ja/appengine/kb/general.html#erroruris

macのGAE Launcherでdebugログが出ない

Google App Engineのmac用環境で、ログ出力を実行してもdebugレベルのログが出力されない。

import logging

logging.info("これは出力される")
logging.debug("これは出力されない")

多分、サーバプロセス起動時にモードを変更する引数を渡せばよいのだと思うけど、macなのでそもそもコマンドラインの引数の渡し方がわかっていません。調査中です。

引数の渡し方がわかりました。
・Google App Engine Launcer上で、リストされているアプリケーションをダブルクリック
・"Extra flags"にフラグを追加
です。
参考URL:
http://blog.docuverse.com/2009/01/30/google-app-engine-launcher-options/

2009年10月3日土曜日

メールを送ろうとしてエラー

Google App Engineでメールを送ろうとしたら次のエラーが発生した

Traceback (most recent call last):
File "/base/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 509, in __call__
handler.post(*groups)
File "/base/data/home/apps/golfpaper/1.336764943207147696/main.py", line 83, in post
, body
File "/base/python_lib/versions/1/google/appengine/api/mail.py", line 239, in send_mail
message.send(make_sync_call)
File "/base/python_lib/versions/1/google/appengine/api/mail.py", line 714, in send
raise ERROR_MAP[e.application_error](e.error_detail)
InvalidSenderError: Unauthorized sender

原因を検索中...

メールを送信するときのアドレスが、アプリケーションに登録されている必要がある。
登録する方法は、
1. http://appengine.google.com/ を開き、対象となるアプリケーションをクリックする
2. Administration - Developersを選択する
3. メールアドレスを登録する
こんな感じでいけそうです。

2009年8月26日水曜日

「はじめてのiPhoneプログラミング」を試す

「はじめてのiPhoneプログラミング」は、amazonなどでも評価の高い一冊。なるほど、わかりやすい内容になっている。でもOS 2.xをベースとして書かれているのと、省略されている事が多いので、本の通りにやってもうまく行かない事が多い。そんな詰まった事を、ここに書いておきます。

・第7章 タブバーとピッカー
P161
サンプルでは、@interfaceの中の宣言でIBOutletにより*window変数を修飾しているが、Xcodeが吐き出すスケルトンコードでは@propertyでIBOutletを修飾している。これはどちらでもよいみたい。

P161
Viewアイコンをクリックしてサイズインスペクタを開き、ビューの高さを411にすることと書かれているが、実は編集ができない状態になっている。このようなときは、Apple + 1で属性インスペクタを開き"Status bar"の値を確認する。ここがデフォルトでは"None"以外の値が設定されている。これを"None"にすることでビューの高さを変更できるようになる。

2009年7月9日木曜日

FLOSS桜山で発表できず、残念

OpenVZに関する勉強の成果をFLOSS桜山で発表しようと思ったのですが、プロジェクターで投影できないというありがちな事象のため発表できませんでした。主催の方にいろいろとりなしていただきましたが、やはり残念だし、もしかして楽しみにしていた方がいれば申し訳ないと思います。
プロジェクターがうまくいかないというのはありがちなことだし、そういう意味ではリスク管理が足りなかったなと反省しています。次回チャンスをいただけるのであれば、万全の態勢で臨みたいと思います。まずは、発表できなかった内容をこのblogで公開していきたいと思います。

2009年6月21日日曜日

OpenVZ #2

CentOS 5の上でOpenVZを導入するにあたって、vethを使ってネットワークを構築するときに得たノウハウを公開しておきます。

用語解説
HN:OpenVZが稼働しているホストマシン(ハードウェアノード)
CT:vzctl createで作成した仮想マシン(コンテナ)

HN上に複数のCTを構築する

この作業は、必ずコンソール上から行ってください。SSHなどネットワークを経由しているときには、途中で一時的にネットワークがつながらなくなるため、作業続行不能となります。

#1の記事にそって、もうひとつCTを作成します(IP:10.0.1.102)
そしてHNから各CTに対してpingを打つと、きちんと結果が返ってきます。

[root@hn ~]# ping -c4 10.0.1.101
PING 10.0.1.101 (10.0.1.101) 56(84) bytes of data.
64 bytes from 10.0.1.101: icmp_seq=1 ttl=64 time=0.093 ms
64 bytes from 10.0.1.101: icmp_seq=2 ttl=64 time=0.110 ms
64 bytes from 10.0.1.101: icmp_seq=3 ttl=64 time=0.109 ms
64 bytes from 10.0.1.101: icmp_seq=4 ttl=64 time=0.113 ms

--- 10.0.1.101 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.093/0.106/0.113/0.010 ms
[root@hn ~]# ping -c4 10.0.1.102
PING 10.0.1.102 (10.0.1.102) 56(84) bytes of data.
64 bytes from 10.0.1.102: icmp_seq=1 ttl=64 time=0.122 ms
64 bytes from 10.0.1.102: icmp_seq=2 ttl=64 time=0.116 ms
64 bytes from 10.0.1.102: icmp_seq=3 ttl=64 time=0.110 ms
64 bytes from 10.0.1.102: icmp_seq=4 ttl=64 time=0.115 ms

--- 10.0.1.102 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 0.110/0.115/0.122/0.013 ms

しかし、CTからCTにはpingが通りません。
[root@ct101 /]# ping -c4 10.0.1.102
PING 10.0.1.102 (10.0.1.102) 56(84) bytes of data.
From 10.0.1.101 icmp_seq=2 Destination Host Unreachable
From 10.0.1.101 icmp_seq=3 Destination Host Unreachable
From 10.0.1.101 icmp_seq=4 Destination Host Unreachable

--- 10.0.1.102 ping statistics ---
4 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2999ms
, pipe 3

これは、HNにあるveth101.0とveth102.0がネットワーク的につながっていないのが原因です。
eth0(CT101) --- veth101.0(HN) --|ここが切れている| -- veth102.0(HN) --- eth0(CT102)

HN側に作成された二つの仮想ネットワークインターフェイス(veth101.0, veth102.0)を接続するためには、HN内に仮想のブリッジを作成します。

[root@hn ~]# yum install bridge-utils
[root@hn ~]# brctl addbr vzbr0
[root@hn ~]# brctl addif vzbr0 eth
[root@hn ~]# brctl addif vzbr0 veth101.0
[root@hn ~]# brctl addif vzbr0 veth102.0
[root@hn ~]# ifconfig eth0 down
[root@hn ~]# ifconfig eth0 0.0.0.0 promisc up
[root@hn ~]# ifconfig vzbr0 192.168.0.101 up
[root@hn ~]# route add -net 10.0.1.0 netmask 255.255.255.0 vzbr0
[root@hn ~]# route
ernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.1.0 * 255.255.255.0 U 0 0 0 vzbr0
192.168.0.0 * 255.255.255.0 U 0 0 0 vzbr0
169.254.0.0 * 255.255.0.0 U 0 0 0 vzbr0
default 192.168.0.230 0.0.0.0 UG 0 0 0 vzbr0

これでct101とct102から、それぞれ別の子サーバへのpingが通るようになります。

2009年6月17日水曜日

OpenVZ #1

CentOS 5の上でOpenVZを導入するにあたって、vethを使ってネットワークを構築するときに得たノウハウを公開しておきます。

用語解説
HN:OpenVZが稼働しているホストマシン(ハードウェアノード)
CT:vzctl createで作成した仮想マシン(コンテナ)

まずは、HN上でvzctl createを実行してCTを作成し、vzctl enterでCTにログインできる状態までたどり着いてください。そこまでの道のりについては
http://wiki.openvz.jp/index.php/%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB
あたりが参考になります。


HN上に一つのCTを構築する

HNのeth0のアドレスは192.168.0.101/24とします。
CTに新規に作成するeth0のアドレスは10.0.0.101/24で作成します。

[root@hn ~]# vzctl create 101 --ostemplate centos-5-x86
Unable to get full ostemplate name for centos-5-x86
Creating container private area (centos-5-x86)
Performing postcreate actions
Container private area was created

[root@hn ~]# vzctl set 101 --hostname ct101 --save
Set hostname: ct101
Saved parameters for CT 101

[root@hn ~]# vzctl set 101 --netif_add eth0 --save
Saved parameters for CT 101

[root@hn ~]# vzctl start 101
Starting container ...
Container is mounted
Setting CPU units: 1000
Configure meminfo: 65536
Set hostname: ct101
Configure veth devices: veth101.0
Container start in progress...

[root@hn ~]# ifconfig veth101.0
veth101.0 Link encap:Ethernet HWaddr **:**:**:D4:49:6C
inet6 addr: ****::****:****:fed4:496c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

[root@hn ~]# echo 1 > /proc/sys/net/ipv4/conf/veth101.0/forwarding
[root@hn ~]# echo 1 > /proc/sys/net/ipv4/conf/veth101.0/proxy_arp
[root@hn ~]# echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
[root@hn ~]# echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
※上記四行のコマンドは、HN上でsysctlコマンドの実行状況によっては不要かもしれない

[root@hn ~]# vzctl enter 101
entered into CT 101

[root@ct101 ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr **:**:**:26:E2:55
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

[root@ct101 ~]# ifconfig eth0 0
[root@ct101 ~]# ifconfig eth0 netmask 255.0.0.0
[root@ct101 ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr **:**:**:26:E2:55
inet addr:10.0.0.101 Bcast:10.255.255.255 Mask:255.0.0.0
inet6 addr: ****::****:****:fe26:e255/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:384 (384.0 b)

ここまでの作業でCTにネットワークインターフェイスを作成することが出来ました。
しかし、CTからHNにpingを打っても返事が返ってきません。

[ve101]# ping 192.168.0.101
connect: Network is unreachable

これは、CTとHNの双方に適切なルーティングの設定をしていないのが原因です。
つまり、CT上には10.0.1.0/24ネットワークに対するルーティングの定義しかないので出ることができず、HN上には192.168.0.0/24ネットワークに対するルーティングの定義しかないので帰ってくることができないのです。だからCTとHNの双方にお互いのネットワークへのルーティングを定義します。

[root@ct101 ~]# ip route add default dev eth0
[root@ct101 ~]# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 * 255.0.0.0 U 0 0 0 eth0
default * 0.0.0.0 U 0 0 0 eth0

[root@ct101 ~]# exit
[root@hn ~]# ip route add 10.0.0.101 dev veth101.0
[root@hn ~]# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.101 * 255.255.255.255 UH 0 0 0 veth101.0
192.168.0.0 * 255.255.255.0 U 0 0 0 eth0
169.254.0.0 * 255.255.0.0 U 0 0 0 eth0
default 192.168.0.230 0.0.0.0 UG 0 0 0 eth0

これでpingが通るようになりました。

[root@hn ~]# ping 10.0.0.101 -c 4
PING 10.0.0.101 (10.0.0.101) 56(84) bytes of data.
64 bytes from 10.0.0.101: icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from 10.0.0.101: icmp_seq=2 ttl=64 time=0.112 ms
64 bytes from 10.0.0.101: icmp_seq=3 ttl=64 time=0.112 ms
64 bytes from 10.0.0.101: icmp_seq=4 ttl=64 time=0.116 ms

--- 10.0.0.101 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 0.095/0.108/0.116/0.015 ms

2009年6月6日土曜日

mission imposibble

さくらの専用サーバで、OpenVZを使って仮想化環境を作る話は、結局完成しませんでした。

・第1の失敗
OpenVZでカーネルを差し替えるときに、差し替え用のカーネルがCPUの種類やメモリの使用量などによって何種類かに分かれます。
cat /proc/cpu
で確認したところマルチコアCPUだったので、まずはマルチCPU用のカーネルに差し替えて再起動を行ったところ、再起動せず。どうやらカーネルパニックになってしまった様子。

→ サポートに再起動依頼。5,250円支払いました。

・第2の失敗
おそらくは一番安全なシングルCPU用のカーネルを使えばいいだろうと思うも、再び有料の再起動をしたくはないので手を考えることにしました。方法としては、カーネルを差し替えて再起動するときにパニックになったら次のカーネルを使うよう、fallback設定をgrubに対して行います。こんな感じです。

default=0
fallback 1
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS_OpenVZ (2.6.xx-xxstub.x.xx.el5) ←xxのところは、もう設定が残っていない
root (hd0,0)
kernel /vmlinuz-2.6.18-xx.xstub.xx.el5 ro root=/dev/sda2
initrd /initrd-2.6.18-128.1.10.el5.img
title CentOS (2.6.18-128.1.10.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-128.1.10.el5 ro root=/dev/sda2
initrd /initrd-2.6.18-128.1.10.el5.img

しかし再起動すると、再び反応なし。想定通りなので再起動してもらうと、やはり反応なし。おかしいなと思ってサポートに再び電話。その結果、カーネルは正常に起動しているが、ネットワークインターフェイスがダウンしているということ。

→といわれてもどうしようもないので、再び再起動依頼。5,250円


その後、Xenを一度動かしてその上でOpenVZを動かそうとも考えましたが、Xenもカーネル差し替えが必要だということがわかり、あきらめモードです。
まあ、仮想化ができなくてもそれなりにやりたいことはできるので、次の一手に進みたいと思います。

次はOpenVPNです。

2009年6月1日月曜日

最初の設定

さくらの専用サーバ上に、OpenVZを使って仮想環境を作り、Webアプリケーションなどの公開を行えるようにする。各仮想環境にはOpenVPNを使って入れるようにする。

★グローバルIPを持ったGWの設定

■ホスト名の修正
デフォルトのホスト名はlocaldomain.localhostとなっていた。これを修正する。修正ファイルは次の通り。
/etc/hosts
/etc/sysconfig/network

■セキュリティホールの可能性をふさぐ
chkconfig --list | grep 3:onでOS起動時に合わせて起動するサービスの確認
→sendmailが動いていた。

chkconfig sendmail offでサービスを起動しないようにする。
/etc/init.d/sendmail stopでサービスを停止する。

その他のサービスは、動いていてもよいようだ。

これで基本的な設定は完了とする。

2009年5月30日土曜日

concrete5

こんな要件を満たすために、CMSツールを探してました。
・CMSサイトそのものは、自分が構築する
・しかしCMSサイトの記事を投稿するのは別の人(つまり管理者じゃない人)
・別の人は、あまりITには詳しくない若者(もっといえば、現役の高校生)
・記事の公開には、別途責任者(=顧問の先生)の許可が必要

検討したのは次のCMS
・SOY CMS
・Movable Type
・Wordpress
・concrete5

SOY CMSは、自分で運営するには構成がシンプル(特にテンプレートがほぼHTMLなところ)が気に入っているのですが、実際にメンテナンスする人にもそれなりの知識が必要そうなのでNG。
Movable Typeは、個人が情報を発信する以外のときはお金がかかりそうなのでNG。
Wordpressは、「CMSで使うこともできますよ」と謳うわりにはそれ用のテンプレートがなく、ずいぶんと構築に手間がかかりそうなのでNG。

というわけでconcrete5がなかなかよさそうなので、採用となりました。良い点としては
・WYSISWYGな編集画面があること→素人にはとっつきやすい。
・CMSの約束事が少ないこと→イコール共通化に関する機能が少ないということですが、そこが却ってよい。
・記事の公開に承認プロセスが踏めること→必須機能なので。

しかし感じたのは、どのツールも導入がかなり考えられているということ。導入がとっつきにくいものは、やはりデファクトスタンダードや大きなシェアを占めるのは難しいということなのでしょう。どのツールも大体5~10個の質問に答えるだけで、最初のサイトが構築できます。これは見習うべきところでしょう。

ちなみに作ったページは、これになる予定です。
http://www.ostmeerphilharmoniker.com/tokai/

2009年5月24日日曜日

さくらの専用サーバー

若手を集めて「技術部」を作ろうと思う。いわゆる部活動だ。
その本気度を示すために、まずは自腹で専用サーバーを契約してみた。
OpenVZやXenなどで仮想化などをやってみたい。
オリジナルサービスとか作って公開して、友達に自慢してみたい。

そんなこんなが月々7,800円なら安いもんだ。

2009年5月8日金曜日

centos5.3でmysqld起動時にyumが実行できない

mysqldが起動中にyumを実行すると、次のエラーが出てきます。

[root@lunch /]# yum update
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Traceback (most recent call last):
File "/usr/bin/yum", line 29, in ?
yummain.user_main(sys.argv[1:], exit_code=True)
File "/usr/share/yum-cli/yummain.py", line 229, in user_main
errcode = main(args)
File "/usr/share/yum-cli/yummain.py", line 104, in main
result, resultmsgs = base.doCommands()
File "/usr/share/yum-cli/cli.py", line 339, in doCommands
self._getTs(needTsRemove)
File "/usr/lib/python2.4/site-packages/yum/depsolve.py", line 101, in _getTs
self._getTsInfo(remove_only)
File "/usr/lib/python2.4/site-packages/yum/depsolve.py", line 112, in _getTsInfo
pkgSack = self.pkgSack
File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 591, in
pkgSack = property(fget=lambda self: self._getSacks(),
File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 434, in _getSacks
self.repos.populateSack(which=repos)
File "/usr/lib/python2.4/site-packages/yum/repos.py", line 223, in populateSack
self.doSetup()
File "/usr/lib/python2.4/site-packages/yum/repos.py", line 71, in doSetup
self.ayum.plugins.run('postreposetup')
File "/usr/lib/python2.4/site-packages/yum/plugins.py", line 176, in run
func(conduitcls(self, self.base, conf, **kwargs))
File "/usr/lib/yum-plugins/fastestmirror.py", line 181, in postreposetup_hook
all_urls = FastestMirror(all_urls).get_mirrorlist()
File "/usr/lib/yum-plugins/fastestmirror.py", line 333, in get_mirrorlist
self._poll_mirrors()
File "/usr/lib/yum-plugins/fastestmirror.py", line 376, in _poll_mirrors
pollThread.start()
File "/usr/lib/python2.4/threading.py", line 416, in start
_start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread

現在、調べているところです。

2009年5月6日水曜日

作成情報と更新情報

近頃はすべてのテーブルに、作成日・作成者・更新日・更新者の4フィールドを持たせる設計が多いです。この列を持たせる理由としては、おもにデータの作成された状態をトレースするためですが、改めてこの列の存在価値を考えたいと思います。

メリットとしては、論理的に間違ったデータが入った時にその登録経路のヒントとなることです。更新時間や更新者(あるいは更新モジュール)が分かれば、プログラムのどの場所に間違いがあるのか簡単に判明することがあります。
しかしデメリットも考えると多々あります。
まずこの情報は、最初と最後しか記録していません。そのため時間の経ってしまったデータについては、間でどのような書き換えが行われたかが不明です。
次に、データを書き出すプログラムが更新者や更新日を正しく書き出しているという前提も必要です。更新者や更新日情報を更新せずにデータだけ更新していたら、かえって問題の発見を遅らせてしまいます。
さらには、OracleでいうSQL-Plusのようなクライアントツールで直接SQL文を発行したときの情報も取得できません。

それらも踏まえると、次のような作戦もありなのではないでしょうか?
・トリガーを使って、履歴用のテーブルに更新者と更新日を記録する。
→テーブル名、操作(CRUD)、更新日、更新者、更新モジュールID、主キーを列とする履歴テーブルにとにかく記録していく。履歴は追えるが内容までは追えない。パフォーマンスに難あり?
・記録しない
中途半端な情報ならば、いっそ記録しないという手もあります。Oracleなどであれば、その気になればアーカイブログやREDOログなどから更新履歴を取得することも可能です。

何のために情報を残すのかを改めて考え直せば、どのレベルまで履歴を取っておくべきか答えは見えてくるはず。

2009年5月5日火曜日

トレーサビリティ

ここ数年間の間、システム開発をするには「トレーサビリティ」が重要だという思いが強くなっている。
たとえばコードを書いたときには、それが設計書のどの部分に対応しているのか?
たとえばテスト設計を書いたときには、それが設計書のどの部分に対応しているのか?
これがきちんと説明できないときには、そのコードやテスト設計を書いた人はたぶんわかっていないまま書いている。
そういう非連続性を見つけ出すためには、レビューが重要。というかレビューの重要な観点の一つがトレーサビリティ。