2010年7月5日月曜日

CentOS 5.5でiscsiターゲットの簡単構築

iSCSIを利用すると、複数ノードから同時に利用できる共有ディスクとして利用することが可能です。 このときに、ディスク側のデバイスとしては、iSCSI対応のストレージを利用することもできますが、お手軽に試験などに利用したいときは、LinuxのiSCSIターゲット機能を利用することができます。 そこで、CentOS5.5で、iSCSIターゲットをお手軽構築する手順を説明します。

1. OSのインストール
CentOSインストール時に、後でiSCSIターゲットとして公開するためのディスク領域を空き領域のパーティションとして、あらかじめ確保しておきます。

2. iSCSI用ディスク領域の準備
fdiskなどで、iSCSIディスクとして利用するためのブロックデバイスを作成します。今回は、「/dev/sda3」としてブロックデバイスを用意しました。

3. scsi-target-utilsパッケージのインストール
yumコマンドでscsi-target-utilsパッケージをインストールします。依存関係パッケージも一緒にインストールする必要があります。

# yum install scsi-target-utils 

4. tgtdの起動
iSCSIターゲットの処理を行うtgtdを起動します。
# /sbin/service tgtd start 

5. iSCSIターゲット用ディスクの設定
iSCSIターゲットのディスクは、tgtadmコマンドで設定しますが、より簡単に作成するためのコマンドとして、tgt-setup-lunコマンドが用意されています。 tgt-setup-lunコマンドの詳細はmanで確認することができます。

# man tgt-setup-lun

今回は、/dev/sda3をディスクとして使用し、iSCSIイニシエーターとして、10.0.102.41と10.0.102.42から接続するため、次のコマンドを実行しました。 
# tgt-setup-lun -d /dev/sda3 -n iscsi-vol1 10.0.102.41 10.0.102.42
Using transport: iscsi
Creating new target (name=iqn.2001-04.com.iscsifs-iscsi-vol1, tid=1)
Adding a logical unit (/dev/sda3) to target, tid=1
Accepting connections only from 10.0.102.41 10.0.102.42

6. 動作確認
tgt-adminコマンドの-sオプションで、ディスクがiSCSIターゲットとして認識されていることを確認します。

# tgt-admin -s 

Target 1: iqn.2001-04.com.iscsifs-iscsi-vol1
    System information:
        Driver: iscsi
        State: ready
    I_T nexus information:
    LUN information:
        LUN: 0
            Type: controller
            SCSI ID: IET     00010000
            SCSI SN: beaf10
            Size: 0 MB
            Online: Yes
            Removable media: No
            Backing store type: rdwr
            Backing store path: None
        LUN: 1
            Type: disk
            SCSI ID: IET     00010001
            SCSI SN: beaf11
            Size: 153097 MB
            Online: Yes
            Removable media: No
            Backing store type: rdwr
            Backing store path: /dev/sda3
    Account information:
    ACL information:
        10.0.102.41
        10.0.102.42

8. /etc/tgt/targets.confの設定
再起動時に、自動的に上記の設定が有効になるように、/etc/tgt/targets.confに以下の設定を追加します。

<target iqn.2001-04.com.iscsifs-iscsi-vol1>
 backing-store /dev/sda3
 initiator-address 10.0.102.41
 initiator-address 10.0.102.42
</target>


7. tgtdの自動起動の設定
設定内容に問題が無ければ、マシン起動時にtgtdが自動起動するように設定しておきます。
# /sbin/chkconfig tgtd on


以上でCentOS5上でのiSCSIターゲットの構築は完了です。

2010年7月2日金曜日

[samba] 所属グループ数の制限を超えるとpanic

最近のSambaでは、setgroups()が失敗するとpanicとなるように実装が変更されていた。

smbd/sec_ctx.c
        if (sys_setgroups(gid, ngroups, groups) != 0 && !non_root_mode()) {
                smb_panic("sys_setgroups failed");
        }

この理由について、こちらで述べられている。
http://old.nabble.com/sys_setgroups-:-migration-issues-from-3.0-series-to-3.2-3.3-series-td23103672.html

要約すると、「setgroups()に失敗したままだと、実際にはグループの権限を持っていないためアクセスできるはずのファイルやディレクトリにアクセスできなくなるのに、それが分からずに問い合わせが多発するから。」ということ。

これが問題になりやすいのは、Solaris10の環境だと思う。
デフォルトだと、最大16グループなので、ファイルサーバー的な利用においては、あっという間に16グループに達する。
とりあえず、OSの/etc/systemに「set ngroups_max=32」を書けば32まで増やせるが、これでも足りない環境だと対策のしようがない。

Solaris10 + ZFS + Sambaを薦めたいときの、一番の弱点。

2010年6月30日水曜日

Movable TypeからBloggerへの移行

所有ドメインの更新時期が近づいてきたこともあって、レンタルサーバーに構築しているMovableTypeをどうするか考えた結果、GoogleのBloggerへ移行することに決定。

Bloggerを登録してから、次の手順で簡単にBloggerへ移行することができた。
  1.  Movable Typeのブログ管理画面から、「ツール」-「エクスポート」でMovable Typeのブログをテキストファイルのデータとして取り出す。
  2. http://movabletype2blogger.appspot.com/に、取り出したテキストファイルをアップロードして、convertする。
  3. できあがったblogger-export.xmlを、Bloggerのインポートでインポートする。
以上、15分ぐらいの作業だった。

2010年4月21日水曜日

PythonでPHPのopenssl_verify()相当の処理

PythonでPHPのopenssl_verify()の処理を実現しようとしたが、RHEL5に入っているM2Cryptoのバグにヒットした。

https://bugzilla.osafoundation.org/show_bug.cgi?id=7973

EVP.verify_final()に署名の情報を渡せないので、署名の検証が行えないというバグ。
最新版のM2Cryptoなら直っている。 2行ぐらい直すだけだけど。

openssl_verify()はこんな感じの実装になった。

def openssl_verify(data, sig, pubkeyfile):
rsa = M2Crypto.RSA.load_pub_key(pubkeyfile)
pubkey = M2Crypto.EVP.PKey()
pubkey.assign_rsa(rsa)
pubkey.reset_context()
pubkey.verify_init()
pubkey.verify_update(data)
return pubkey.verify_final(sig)



2010年4月9日金曜日

PythonでPHPのopenssl_seal()相当の処理を実現

PHPには、openssl_seal()が用意されていて、複数の受信者に対して、受信者ごとの公開鍵で暗号化したデーターを、一度に暗号化するインターフェースが用意されている。

これと同じことを、Pythonでやろうとすると、インターフェースが用意されていないので、M2Cryptoを利用してやる必要があるが、その方法がやっと分かった。

まず、opensslコマンドでテスト用に、公開鍵と秘密鍵を作成しておく。

$ openssl genrsa -out privatekey.pem
$ openssl rsa -pubout -in privatekey.pem -out publickey.pem


次にPythonの暗号化用のスクリプトで、データーを暗号化し、暗号化したデーターと、エンベロープキーをゲットする。

#!/usr/bin/python

import M2Crypto
import M2Crypto.Rand
import M2Crypto.RSA
import base64

PUBKEY = "publickey.pem"
message = "Hello World!"

pubkey = M2Crypto.RSA.load_pub_key(PUBKEY)
randdata = M2Crypto.Rand.rand_bytes(16)
msg = pubkey.public_encrypt(randdata,M2Crypto.RSA.pkcs1_padding)
print "== envelope key (Base64 encoded) =="
print base64.b64encode(msg)

cipher='rc4'
iv = ""
enc = M2Crypto.EVP.Cipher(cipher, randdata, iv, M2Crypto.encrypt)
data = enc.update(message)
data += enc.final()

print "== encrypted data (Base64 encoded) =="
print base64.b64encode(data)


これを実行すると、次のような結果が得られる。

== envelope key (Base64 encoded) ==
NIBGzm6ijGFjtruyVO4QDBGiWNu1bgJvJPlkY5kmCNLKEuabiBytsjRfOKZb7w4jsSnCrUREeCPHwa7SLMVceNQf6iWyE22RS6tAMVvzFBrKjXwNCZ+pU4v4pCQPTI+vZg7B/QcajR832hmBcG0NF8LRl1+9rSSvNpPMwJNTwos=
== encrypted data (Base64 encoded) ==
on5LIKdw1UxqfcYY


これらのデーターが復号化できることを、PHPのスクリプトでopenssl_open()を使って確認してみる。

$privatekey = file_get_contents("privatekey.pem");
$message= "";
$encrypted = "on5LIKdw1UxqfcYY";

$ekey = "NIBGzm6ijGFjtruyVO4QDBGiWNu1bgJvJPlkY5kmCNLKEuabiBytsjRfOKZb7w4jsSnCrUREeCPHwa7SLMVceNQf6iWyE22RS6tAMVvzFBrKjXwNCZ+pU4v4pCQPTI+vZg7B/QcajR832hmBcG0NF8LRl1+9rSSvNpPMwJNTwos=";

if (!openssl_open(base64_decode($encrypted), $message, base64_decode($ekey), $privatekey)){
echo "Failed decrypt\n";
die;
}
echo $message."\n";
?>


このPHPスクリプトを実行して、"Hello World!"が表示されれば、正しく復号化できたということ。


2010年4月6日火曜日

Python から Cを利用

PythonからCのライブラリを利用するときに、Pythonのリストオブジェクトをどのように利用するか調べてみた。

リストオブジェクトに入っている文字列を表示し、リストオブジェクト内のオブジェクト数を返却するCプログラムを、test2モジュールとして作成してみた。

#include <Python.h>

static PyObject *
test2_listnum(PyObject *self, PyObject *args)
{
PyObject *list;
PyObject *item;
char *itemstr;
int num;
int i;
if (!PyArg_ParseTuple(args, "O", &list)){
return NULL;
}
num = PyList_Size(list);

for (i=0;iitem = PyList_GetItem(list, i);
itemstr = PyString_AsString(item);
printf("%s\n", itemstr);
}

return Py_BuildValue("i", num);
}


これをビルドするためのMakefile。

CC = gcc

.c.o:
$(CC) -fPIC -I"/usr/include/python2.4" -c $<

all: test2

clean:
rm -r *.o; rm -r *.so

test2: test2.o
$(CC) $(OPT) -Wl,-soname,$@.so -shared -o $@.so $^


そして、テスト用のPythonプログラム。

#!/usr/bin/python

import test2

a = []
a.append("test1")
a.append("test2")
num = test2.listnum(a)
print num



2010年4月1日木曜日

Perl CPAN::Siteの仕様変更

ネットワークアプライアンスのInfobloxで提供されるPerl APIを利用するために、マニュアルに従って、Perl CPAN::Siteの最新版(1.05)をインストールした。

ドキュメントに従って、
# perl -MCPAN::Site -e shell
を実行すると、何も起きずにすぐ終了してしまう。
straceをかけてみたが、エラーらしきエラーもなし。

いろいろ調べていくうちに、CPAN::Siteのドキュメントに、1.01から仕様が大幅に変更されたとか書いてある。
もしやと思って、ちょっと古い CPAN::Site 0.26に入れ替えてみたら、ドキュメント通りに動作するようになった。
ありがちな罠だけど、これは一般人には解決できない気がしたので、メモを残しておく。