Home > Archives > 2009年10月10日

2009年10月10日

物理ディスク上のパーティションを個別にVMwareのディスクとして使うのを手動でやろうか

VMware Workstation 使って新しいVM作れば簡単に出来るんだけど,貧乏人としては自前でmvdkファイルをどうにか書きたいなと.ネットで検索すると,物理ディスク全体を仮想ディスクにする方法はちらほら見られるけれど,パーティション単位で扱っている方法が見つからない.ディスク丸ごとだとちと怖いのでどうにかしたい.

ということで,実際に VMware Workstation で物理パーティションにアクセスする仮想ディスクを作って,その内容と fdisk の情報から自前でmvdkファイルを書くための情報を推測してみた.

とりあえず fdisk の情報.先頭にリカバリ情報のパーティションがあり,そのあとに二つのNTFSパーティションが置かれている.

Disk /dev/sda: 320.0 GB, 320072933376 bytes
255 heads, 63 sectors/track, 38913 cylinders
Units = シリンダ数 of 16065 * 512 = 8225280 bytes
Disk identifier: 0x00000021
 
デバイス Boot      Start         End      Blocks   Id  System
/dev/sda1               1        1275    10241406   27  不明
/dev/sda2   *        1276       13417    97530615    7  HPFS/NTFS
/dev/sda3           13418       38913   204796620    7  HPFS/NTFS

そんで,最初のパーティションを仮想ディスクとする生成された vmdk ファイル.

# Disk DescriptorFile
version=1
encoding="Shift_JIS"
CID=edce33f3
parentCID=ffffffff
createType="partitionedDevice"
 
# Extent description
RW 63 FLAT "partition-pt.vmdk" 0
RW 20482812 FLAT "\\.\PhysicalDrive0" 63
RW 195061230 ZERO 
RW 409593240 ZERO 
RW 5103 ZERO 
 
# The Disk Data Base 
#DDB
 
ddb.virtualHWVersion = "7"
ddb.uuid = "60 00 C2 9f 15 8c 38 89-2c be 12 94 46 3a 8c ea"
ddb.geometry.cylinders = "16383"
ddb.geometry.heads = "16"
ddb.geometry.sectors = "63"
ddb.geometry.biosCylinders = "1024"
ddb.geometry.biosHeads = "255"
ddb.geometry.biosSectors = "63"
ddb.adapterType = "ide"

まず,パーティション単位で仮想ディスクとするには partitionedDevice というタイプを指定するらしい.そんで, Extent description にディスクのパーティション構造らしきものが書かれるらしい.

最初の行はディスク先頭のMBRを含む63セクタでしょう.多分RWの後の数字がセクタ数.そしてこの部分は物理ディスク上に書き込まれては困るので別ファイル(partition-pt.vmdk)に内容を置くと.ファイル名手前の FLAT はよく分からんけどデータの保存の形か何かかね? そんで最後の数字の 0 は開始セクタ番号か何かでしょう(イメージ中のセクタ数と考えるのが妥当か?).ところで行先頭のRWはread/writeなのかrawなのか?

んで,次の行が最初のパーティションを使うためのエントリのはず.RWの後の数字がfdiskで見たブロック数の倍になっているからパーティションのセクタ数で良いっぽい.ついで FLAT は相変わらず.そして最初のディスクなので先ほどのファイル名の変わりに"\\.\PhysicalDrive0"が置かれ,開始セクタと思われる63が続くと.

残りの行は各パーティションのセクタ数と ZERO が書かれるらしい.ZEROは使用しない領域を表すのかね?

DDBは仮想ディスクとしてのスペックなのであまり気にしない.ネット上に転がってる物理ディスク全体を仮想ディスクにする場合と同じ値みたいだし.

例がひとつでは分かりにくいので,三つ目のパーティションを使った仮想ディスクの vmdk ファイルも生成.

# Disk DescriptorFile
version=1
encoding="Shift_JIS"
CID=e82adf55
parentCID=ffffffff
createType="partitionedDevice"
 
# Extent description
RW 63 FLAT "Ubuntu-pt.vmdk" 0
RW 20482812 ZERO 
RW 195061230 ZERO 
RW 409593240 FLAT "\\.\PhysicalDrive0" 215544105
RW 5103 ZERO 
 
# The Disk Data Base 
#DDB
 
ddb.virtualHWVersion = "7"
ddb.uuid = "60 00 C2 95 b8 17 da cc-f3 65 27 46 17 81 e6 07"
ddb.geometry.cylinders = "16383"
ddb.geometry.heads = "16"
ddb.geometry.sectors = "63"
ddb.geometry.biosCylinders = "1024"
ddb.geometry.biosHeads = "255"
ddb.geometry.biosSectors = "63"
ddb.adapterType = "ide"

Extent description のエントリが少し変わった.最初の63セクタは同じ(ファイル名は違うけど).そして,今度は第一パーティションを使用しないので2行目が ZERO になった.変わりに,第三パーティションに対応する4行目が FLAT "\\.\PhysicalDrive0" になった.最後の数字は上三行のセクタ数の合計になっているので,パーティションの開始セクタ位置ってことで良いっぽい.

ということで,物理ディスク上のパーティションを使うvmdkファイルを書くポイントのまとめ.

  • createType="partitionedDevice" とする
  • Extent description をパーティションテーブルに沿って書く.各エントリは,RWの後にサイズをセクタ数で指定し,使用するパーティションなら FLAT の後にファイル名と開始セクタ位置を書き,使わないなら ZEROと書く.ファイル名は"\\.\PhysicalDrive0"とかで物理ディスク行き,通常ファイル名でローカルなファイルっぽい.サイズ(セクタ数)は,([End] - [Start]) * [sectors/track] * [heads] で求まる.例えば二番目のパーティションは 195061230 = (13417 - 1276 + 1) * 63 * 255.ただし,最初のパーティションはMBRがあるため 63 セクタ分引かれる(20482812 = (1275 - 1 + 1) * 63 * 255 - 63).

TODO: 拡張パーティションとかどうするんだろう? 本当に使えるのかこれ?

ということで,拡張パーティション入りの場合のExtent description と fdiskの出力 .

RW 63 FLAT "ubun2-pt.vmdk" 0
RW 20482812 ZERO 
RW 195061230 ZERO 
RW 376033455 ZERO 
RW 63 FLAT "ubun2-pt.vmdk" 63
RW 24579387 ZERO 
RW 63 FLAT "ubun2-pt.vmdk" 126
RW 8980272 FLAT "\\.\PhysicalDrive0" 616157073
RW 5103 ZERO 
/dev/sda1               1        1275    10241406   27  不明
/dev/sda2   *        1276       13417    97530615    7  HPFS/NTFS
/dev/sda3           13418       36824   188016727+   7  HPFS/NTFS
/dev/sda4           36825       38913    16779892+   5  拡張領域
/dev/sda5           36825       38354    12289693+  83  Linux
/dev/sda6           38355       38913     4490136   83  Linux

拡張パーティションの持つ拡張パーティションブートレコードもローカルのファイルに持っておくらしい.拡張パーティションになっていようがいまいが,使うパーティションの最後の数字は先頭セクタ番号(それまでのセクタ数の合計)となるらしい.注意点は,拡張パーティション内の領域にある論理パーティションの場合には,RWの後のサイズ(セクタ数)が拡張パーティションブートレコードの分(63セクタ)を引いたサイズになること.例えば,上の例では 8980272 = (38913 - 38355 + 1) * 63 * 255 - 63 となっている.

うーん,パーティションテーブルの中身はどうすればいいのだろうか? dd で元のディスクのテーブルを抜き出したけど不正だと怒られた.よーわからん.

と思ったら抜き出すアドレス間違ってただけだった.元ディスクのパーティションテーブルを抜き出して一つのファイルにまとめてやれば問題ないらしい.

ということで,生成のためのスクリプトとサンプル入力をメモっておく:genvmdk.sh, genvmdk.awk, diskinfo.txt.使うにはメインのスクリプトに入力を食わせる.

./genvmdk.sh < diskinfo.txt

これで仮想ディスク本体の disk.vmdk とパーティションテーブル生成スクリプト gen-pt.sh ができる.あとは

sudo bash gen-pt.sh

とかして dd でパーティションテーブルを抜き取ってきて disk-pt.vmdk ができる.

スクリプトへの入力は,ヘッド数,トラックあたりのセクタ数,ディスク全体のデバイスファイル,仮想ディスクからアクセス可能なパーティション(今のところ一個だけ),fdiskの出力たち.

Home > Archives > 2009年10月10日

Search
Feeds

Page Top