udevを使ってデバイス名の固定する | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

Linux環境上に何らかのデバイスを接続した場合、/devディレクトリ以下に/dev/sdXといったデバイス名が表示されますが、運用の中でデバイスが追加・削除されたりすると名前が変わったりしてシステム上良くないことが起きる場合があります。

特にストレージ領域をマウントしているといった場合、その接続デバイスの名前が変わることで正しくマウントできなくなったり、OS上で動かしているソフトウェアによってはデバイス名を指定しているようなものもあったりして、それが変わるというのは動作に支障が出るケースもあります。

 

今回は、以前に書いた「iSCSI経由でExt4環境のボリュームをマウントする 」のようにiSCSI経由でストレージに接続している環境下で、接続したストレージボリュームのデバイス名を固定化するというやり方を書いてます。

この中でもデバイス名を固定化するやり方は簡単に書いているのですが、ボリューム内にパーティションをきっていた場合、そのパーティション領域のデバイス名がうまく固定化できなかったことから、改めてまとめてます。

なお、ここで動作確認しているOSはCentOS6.6となってます。

udevのバージョンによって設定方法が結構違うみたいなのでOSのバージョンによっては設定内容が異なるかもしれないので注意してください。

 

 

udevを使ってパーティション領域のデバイス名を固定化する

 

というのが今回の趣旨ではあるんですけど、まず最初にOS上でiSCSI経由で接続されているデバイスの一覧をみてみます。

 

# ls -l /dev/disk/by-path/
合計 0
lrwxrwxrwx 1 root root  9  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0 -> ../../sdc
lrwxrwxrwx 1 root root 10  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0-part1 -> ../../sdc1
lrwxrwxrwx 1 root root  9  8月  7 10:35 2015 pci-0000:00:07.1-scsi-1:0:0:0 -> ../../sr0
lrwxrwxrwx 1 root root  9  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0 -> ../../sda
lrwxrwxrwx 1 root root 10  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10  8月  7 10:35 2015 pci-0000:00:10.0-scsi-0:0:0:0-part3 -> ../../sda3

 

先頭の2つがiSCSIでつなげているデバイスで、下記のようにlun-0(sdc)がブロックデバイス、lun-0-part1(sdc1)がパーティションの構成となっています。

 

# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0     11:0    1 1024M  0 rom
sda      8:0    0   16G  0 disk
├sda1   8:1    0  500M  0 part /boot
├sda2   8:2    0 11.6G  0 part /
└sda3   8:3    0  3.9G  0 part
sdc      8:32   0  105G  0 disk
└sdc1   8:33   0  105G  0 part

 

このsdcおよびsdc1というデバイス名を固定化する方法ですが、「iSCSI経由でExt4環境のボリュームをマウントする 」で書いた下記のようなudevのルールファイルを作成するとブロックデバイスに対してはデバイス名を固定化できるのですが、パーティション領域に関してはうまく動作してくれません。

 

KERNEL=="sd*", BUS=="scsi", PROGRAM="/lib/udev/scsi_id -g /dev/%k", RESULT=="36019cbd1a29432cc821b157e1600f0f1", NAME="bar%n", OWNER:="fuga", GROUP:="hoge", MODE:="0660"

 

このルールを適用すると下記のようにブロックデバイスとその中のパーティションとではデバイス名が変わってしまいます。

 

# ls -l /dev/disk/by-path/
合計 0
lrwxrwxrwx 1 root root  9  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0 -> ../../bar
lrwxrwxrwx 1 root root 10  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0-part1 -> ../../sdc1

 

想定としてはパーティションの領域はbar1というデバイス名になってほしいところが元もとのsdc1のままになってます。

実際にデータがおかれているパーティション領域はOS上でマウントする際に/etc/fstabとかに書いたりするのでこのデバイス名も固定化しておきたいところです。

先ほどのルールで何が問題なのかというのは、このファイルでやっていることはPROGRAMで指定したコマンドを叩いてRESULTの結果が一致したら、NAMEに指定しているデバイス名を付けろというものですが、そもそもscsi_idコマンドはブロックデバイスに対してしかSCSI ID(デバイス固有の一意な識別子)を返してくれないみたいです。

 

ってことで、ルールを下記のように変更します。

ファイルは、/etc/udev/rules.d/80-scsi.rulesという名前で保存しています。

 

SUBSYSTEM=="block", ENV{ID_BUS}=="scsi", ENV{ID_SERIAL}=="36019cbd1a29432cc821b157e1600f0f1", NAME="bar%n", OWNER:="fuga", GROUP:="hoge", MODE:="0660"

 

ENV{ID_SERIAL}によって、デバイスのプロパティが指定のSCSI IDと一致した場合にデバイス名をbar%n(%nは順番に振られるデバイス番号)にしろというルールに変更しています。

 

このID_SERIALは下記のコマンドで確認できます。

 

# udevadm info --query=all --name=/dev/bar
P: /devices/platform/host17/session15/target17:0:0/17:0:0:0/block/sdc
N: bar
- snip -
E: UDEV_LOG=3
E: DEVPATH=/devices/platform/host17/session15/target17:0:0/17:0:0:0/block/sdc
- snip -
E: ID_REVISION=6.0
E: ID_TYPE=disk
E: ID_SERIAL_RAW=36019cbd1a29432cc821b157e1600f0f1
E: ID_SERIAL=36019cbd1a29432cc821b157e1600f0f1
- snip -

 

このID_SERIALはブロックデバイスに対してもパーティション領域に対しても同じ結果がセットされているため、ルールファイルの中でうまく マッチングさせることができます。

ルールファイルの表記に関する説明は下記に詳しく書かれています。

 

udevルールを処理するカーネルデバイスイベントへの影響 @ Novell

 

設定変更後は、udevを再起動します。

 

# start_udev
udev を起動中: [  OK  ]

 

これでもう一度、デバイス名を確認していると想定しているとおりbarやbar1のデバイス名になりました。

 

# ls -l /dev/disk/by-path/
合計 0
lrwxrwxrwx 1 root root  9  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0 -> ../../bar
lrwxrwxrwx 1 root root 10  8月 13 17:43 2015 ip-192.168.0.10:1234-iscsi-iqn.storage:0-12345-xxxxxxxxx-disk-lun-0-part1 -> ../../bar1

 

ちなみに、ルールファイルが正しく読み込まれていたり適用されているか確認したい場合は、下記のコマンドでテストをすることができます。

引数に渡しているパスは、先ほどのudevadm infoコマンドの結果の中でDEVPATHに表示されているパスです。

 

# udevadm test /devices/platform/host17/session15/target17:0:0/17:0:0:0/block/sdc
run_command: calling: test
udevadm_test: version 147
This program is for debugging only, it does not run any program,
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

- snip -
parse_file: reading '/etc/udev/rules.d/80-scsi.rules' as rules file
- snip -
udev_rules_apply_to_event: OWNER 502 /etc/udev/rules.d/80-scsi.rules:1
udev_rules_apply_to_event: GROUP 502 /etc/udev/rules.d/80-scsi.rules:1
udev_rules_apply_to_event: MODE 0660 /etc/udev/rules.d/80-scsi.rules:1
udev_rules_apply_to_event: NAME 'bar' /etc/udev/rules.d/80-scsi.rules:1
- snip -

 

かなり大量に情報が出てきますけど、最初のほうにルールファイルを読み込んでいるか、後半のほうにルールファイルに指定された名前などが適用されているかの情報で正しいかどうか読み取れます。

あと、CentOS5とかだとこのルールファイルは20-scsi.rulesのように若い番号で定義していたんですけど、適用する順番が変わったのかこのままだとうまく動作せず、80-scsi.rulesという後半の番号で定義するようにしました。

 

理由はよくわからないのですが、udevのデフォルトルールファイルが/lib/udev/rules.d/にあったりして、この辺のファイルが先に名前をつけてしまっているからなんじゃないかなと思ったりしてます。