しょんぼり技術メモ

まいにちがしょんぼり

XenServer5でシステム上にゲストOSのディスクイメージを作成した環境でゲストのファイルを吸い出したい

某所で使っているサーバが、地震やら停電やらの影響で死んでしまいました。おおさーばよ しんでしまうとはなさけない
そのマシンにはXenServerがインストールしてあり、その上で動作していたゲストOSのファイルにアクセスする必要が出てきました。

さて困った、いったいどうしたらいいのでしょう?

なお、(当然ながら)ディスクイメージはXenServer5のシステムがインストールされたHDDと同じドライブ上にあります。NASやSANを使っているなら別ですが、データを吸い出すためだけにまたXenServerをインストールするのはさすがにめんどくさすぎる…

まずはHDDを覗いてみる

今回はSATAからUSBに変換するアダプタを使ってFedoraマシンに接続しました。/dev/sdbとして認識されています。
fdiskでディスクをのぞいてみると:

# fdisk -l /dev/sdb

ディスク /dev/sdb: 250.1 GB, 250058268160 バイト
ヘッド 255, セクタ 63, シリンダ 30401, 合計 488395055 セクタ
Units = セクタ数 of 1 * 512 = 512 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O size (minimum/optimal): 512 bytes / 512 bytesディスク識別子: 0x00000000
デバイス ブート      始点        終点     ブロック   Id  システム
/dev/sdb1   *          63     8016434     4008186   83  Linux
/dev/sdb2         8016435    16032869     4008217+  83  Linux
/dev/sdb3        16032870   488392064   236179597+  83  Linux

Linuxパーティションが3つあるようです。容量的に、/dev/sdb3がクサいですね。

ゲストOSのデータを探す

とりあえずダメ元でマウントしてみましょう。ext3でディスクイメージがぽーんとおいてあればそれでおしまいですね!

# mount -r /dev/sdb3 /mnt
mount: 未知のファイルシステムタイプ 'LVM2_member'

とまあ、そうは問屋が卸してくれないようです。LVM2を使っているようです。

ということで、ボリュームグループを捜してみましょう。vgscanコマンドで検出させます。

# vgscan
  Reading all physical volumes.  This may take a while...
  Found volume group "VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b" using metadata type lvm2
  Found volume group "vg_hoge" using metadata type lvm2

vg_hogeは操作しているマシンのVGなので、ターゲットは"VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b"になります。

論理ボリュームの情報を見てみましょう。vgchangeコマンドで認識させてから、lvsコマンドで表示させます。

# vgchange -ay VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b
# lvs
  LV                                       VG                                                 Attr   LSize   Origin Snap%  Move Log Copy%  Convert
  MGT                                      VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b -wi-a-   4.00m
  VHD-6e1390fa-f2c7-4c38-8844-71c7e6c9c4b4 VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b -wi-a-  32.07g
  VHD-8fe29de6-8abb-436f-9e28-c7d6003ac49e VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b -wi-a-  32.07g
  lv_root                                  vg_hoge                                            -wi-ao 459.69g
  lv_swap                                  vg_hoge                                            -wi-ao   5.88g

MGT, VHD-6e…, VHD-8f…の3つが見えました。XenServer上に2つのゲストOSを作っていたので、それぞれのものでしょう。MGTはManaGemenTか何かでしょうか?

ゲストOSのデータをマウントする

さて、ここまでの作業で、次のようなことがわかっています。
「VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2bというVG(ボリュームグループ)上に、VHD-8fe29de6-8abb-436f-9e28-c7d6003ac49eというLV(論理ボリューム:従来のパーティションのようなもの)があるらしい」
具体的には、

/dev/VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b/VHD-8fe29de6-8abb-436f-9e28-c7d6003ac49e

というデバイスファイルが存在しています。こいつを何とかして覗いてみよう、というのが目的になります。

ふたたび、ダメ元でマウントしてみましょう。

# mount -r /dev/VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b/VHD-8fe29de6-8abb-436f-9e28-c7d6003ac49e /mnt
mount: ファイルシステムタイプを指定する必要があります

やっぱりだめでした。自動認識されるようなパーティションではないようです。

では、この中身を直接覗いてみることにします。
ddコマンドで先頭1MBを標準出力に書き出して、hexdumpに流し込んでみます。

# dd if=/dev/VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b/VHD-8fe29de6-8abb-436f-9e28-c7d6003ac49e bs=1M count=1 | hexdump -C | less
00000000  63 6f 6e 65 63 74 69 78  00 00 00 02 00 01 00 00  |conectix........|
00000010  00 00 00 00 00 00 02 00  11 de d4 da 74 61 70 00  |............tap.|
00000020  00 01 00 03 00 00 00 00  00 00 00 08 00 00 00 00  |................|
00000030  00 00 00 08 00 00 00 00  40 40 10 ff 00 00 00 03  |........@@......|
00000040  ff ff ef ab 2a 44 a7 be  b1 c0 4d bd a6 3f 65 33  |....*D....M..?e3|
00000050  6f bd 57 1c 00 00 00 00  00 00 00 00 00 00 00 00  |o.W.............|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
(以下略) 

おっと、露骨なマジックナンバが見えますね。conectix…?どこかで聞いたような…


はい、そうです。VirtualPCを作ったConectixです。察しの良い方はもうお気づきでしょう、このファイルはVirtualPCHyper-Vで使われるVHD形式です。

さあ、正体がわかりました。しかし、これをどうしたら良いでしょう?

VHD形式をマウントする

タイトルに偽りあり。直接マウントする方法がわからなかったので、変換することにしましょう。
QEMUのイメージ操作ツールであるqemu-imgがVHD形式に対応しているので、これを使って変換します。

# qemu-img convert -f vpc -O raw /dev/VG_XenStorage-db39cbf5-09ab-c541-6cc9-3f6e2ac6af2b/VHD-8fe29de6-8abb-436f-9e28-c7d6003ac49e /xenserver_disk/xs2.raw

"-f vpc"で入力フォーマットにVHD形式(指定文字列はVirtualPCvpc)を指定し、、"-O raw"で出力フォーマットにRAW形式を指定します。これを/xenserver_disk/xs2.rawに変換させます。ディスクイメージサイズに応じて時間がかかりますので、のんびり待ちましょう。


さて、次はこのraw形式ファイルを料理します。
ファイルを覗いてみると:

# file /xenserver_disk/xs2.raw 
/xenserver_disk/xs2.raw: x86 boot sector; GRand Unified Bootloader, stage1 version 0x3, boot drive 0x80, 1st sector stage2 0x128b7; partition 1: ID=0x83, active, starthead 1, startsector 63, 208782 sectors; partition 2: ID=0x83, starthead 0, startsector 208845, 58492665 sectors; partition 3: ID=0x82, starthead 254, startsector 58701510, 8385930 sectors, code offset 0x48

はい、ディスクイメージですね。(ってqemu-imgにそういうファイルを作れと指示したので当たり前ですが)
fdiskで覗くとこうなりました:

 fdisk -l /xenserver_disk/xs2.raw 
ディスク /xenserver_disk/xs2.raw: 34.4 GB, 34359214080 バイトヘッド 255, セクタ 63, シリンダ 4177, 合計 67107840 セクタ
Units = セクタ数 of 1 * 512 = 512 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O size (minimum/optimal): 512 bytes / 512 bytes
ディスク識別子: 0x0008d334

            デバイス ブート      始点        終点     ブロック   Id  システム
/xenserver_disk/xs2.raw1   *          63      208844      104391   83  Linux
/xenserver_disk/xs2.raw2          208845    58701509    29246332+  83  Linux
/xenserver_disk/xs2.raw3        58701510    67087439     4192965   82  Linux スワップ / Solaris

というわけで、無事にゲストOSのディスクが見えました!
…が、どうやってデータにアクセスしたらよいでしょう?

ゲストOSのデータにアクセスする

さてついに最終章です。RAW形式ファイルの2番目のパーティション上にあるデータにアクセスしたい。
そのためには、「xs2.rawファイル中の2番目のパーティション」をどこかにマウントする必要があります。
loopデバイスを使ってそれを行うことができます。

まず、どのループデバイスが空いているかを調べます。

# losetup -f
/dev/loop0

次に、そのループデバイスにファイルを結びつけましょう。

# losetup /dev/loop0 /xenserver_disk/xs2.raw 
# ls /dev/loop0
/dev/loop0

続いて、kpartxコマンドでパーティションを認識させます。

# kpartx -a /dev/loop0
# ls -l /dev/mapper/loop*
lrwxrwxrwx 1 root root 7 2011-04-17 19:51 /dev/mapper/loop0p1 -> ../dm-5
lrwxrwxrwx 1 root root 7 2011-04-17 19:51 /dev/mapper/loop0p2 -> ../dm-6
lrwxrwxrwx 1 root root 7 2011-04-17 19:51 /dev/mapper/loop0p3 -> ../dm-7

こうして、/dev/mapper/loop0p2 が例のイメージファイルの2番目のパーティションとしてアクセスできるようになりました。
あとはマウントしてやればゲストのファイルが見えるはずです。

# mount -r /dev/mapper/loop0p2 /mnt
# ls /mnt
Users  bin  boot  dev  etc  home  lib  lost+found  media  misc  mnt  net  opt  proc  root  sbin  selinux  srv  sys  tmp  usr  var

やったね!

後片付け

以下のようにして、お片付けをしておきましょう。

# umount /mnt
# kpartx -d /dev/loop0
# losetup -d /dev/loop0

というわけで

XenServerはこわくないよ!