Virtualbox VDI ディスクイメージの論理サイズ縮小

VirtualBox の仮想ディスクのサイズ縮小をしたい。

ホストOSから見た vdiファイルの縮小はよくあるが、今回はゲストOSから見たディスクサイズの縮小のお話。

5年～10年以前に似たようなことをやったときは、ターゲットサイズの別ディスクイメージを作り、縮小元イメージと共にゲストOSでマウントしてddやファイル転送で何とかした。
今はどうなのかな？ いい方法が出現しているかな？


# 経緯

テスト目的で作った、Ubuntu20.04 ゲスト。ディスクはお手軽に 10GiB でいいや！と設定した後、apt upgrade して Xojo をインストールしたら足りなくなった。

さすがに今どき 10GiB じゃ少なすぎたかと思って 100GiB に拡張したら、起動しなくなった。
Disk Geometry が変化したことで問題が発生したかな？ と思い、ハードディスクサイズを縮小することにしました。
100GiB のディスクイメージを 30GiB として起動するまでが目標。

（事後にわかりましたが Disk Geometryの問題ではありませんでした）

# 環境

- ホストOS Windows10
- ゲストOS Ubuntu20.04
- VirtualBox バージョン 6.0.22 r137980 (Qt5.6.2)
- ディスクイメージ 論理サイズ 100GiB のvdi ファイル

vdi ファイルは 10GiB から 100GiB に変更しただけ。パーティーション構成は 10GiB のまままだ変更していない。

# 仮想メディアマネージャーは使えなかった

「ファイル」-「仮想メディアマネージャ」で操作できるディスクサイズの変更作業。

![VirtualBox100G.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/8f5e5fa2-552d-5dcc-1d2d-f71591f4b44d.png)
10GiB → 100GiB はできたが、100GiB → 20GiB などの縮小操作をしようとしたができなかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/65008460-fde2-c8ed-063f-2165ce802cab.png)
上図では、20 GB に警告マークが付き、「適用」が押せなくなっている


# VBoxManageではできなかった

コマンドラインでも試してみた。

MS-Windows で VBoxManage を使うにはパスを通すが、めんどくさいのでフルパスで指定して実行。

```

"C:\Program Files\Oracle\VirtualBox\vboxmanage" modifyhd Ubuntu2004Test.vdi --resize 11000
```

10G にするには10000だが、ギガバイト／ギビバイト換算誤差の可能性を考慮し 11000 とした。

```

0%...
Progress state: VBOX_E_NOT_SUPPORTED
VBoxManage.exe: error: Failed to resize medium
VBoxManage.exe: error: Shrinking is not yet supported for medium 'C:\Users\hoken\VirtualBox VMs\Ubuntu2004Test\Ubuntu2004Test.vdi'
VBoxManage.exe: error: Details: code VBOX_E_NOT_SUPPORTED (0x80bb0009), component MediumWrap, interface IMedium
VBoxManage.exe: error: Context: "enum RTEXITCODE __cdecl handleModifyMedium(struct HandlerArg *)" at line 768 of file VBoxManageDisk.cpp

```

縮小は今でもダメでした。

# ゲストOS間でイメージコピー

正解の方法です。

空の 30GiB のディスクイメージを作り、100GiB のソースディスクと共にマウントします。
Ubuntu インストールCDのISOファイルを使って起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/5637f878-a929-0356-aecf-b43fee7fe08c.png)



```

$ sudo fdisk -l


```
として、ハードディスクイメージのデバイス名を取得します。

```

・
・
・
ディスク /dev/sda: 100 GiB, 107374182400 バイト, 209715200 セクタ
Disk model: VBOX HARDDISK   
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0x29393310

デバイス   起動 開始位置 最後から   セクタ サイズ Id タイプ
/dev/sda1  *        2048  1050623  1048576   512M  b W95 FAT32
/dev/sda2        1052670 20969471 19916802   9.5G  5 拡張領域
/dev/sda5        1052672 20969471 19916800   9.5G 83 Linux


ディスク /dev/sdb: 30 GiB, 32212254720 バイト, 62914560 セクタ
Disk model: VBOX HARDDISK   
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト

```

イメージ転送は dd とか ddrescue とかを使いますが、デバイス名で指定するので間違うと致命的です。間違いのリスクを少しでも減らすために、環境変数にコピー元とコピー先を指定して、それを使うようにします。

```

$ export SOURCE=/dev/sda
$ export DIST=/dev/sdb


```
今回は、イメージ転送ツールに ddrescue を使いました。apt でインストールします。

```

$ sudo apt install gddrescue

```
先ほどの環境変数を使って実行します

```

$ sudo ddrescue $SOURCE $DIST --force
```
以下のような表示になるので、コピー終了まで待ちます。

```

GNU ddrescue 1.23
Press Ctrl-C to interrupt
     ipos:   32212 MB, non-trimmed:        0 B,  current rate:    280 MB/s
     opos:   32212 MB, non-scraped:        0 B,  average rate:  70026 kB/s
non-tried:   75161 MB,  bad-sector:        0 B,    error rate:       0 B/s
  rescued:   32212 MB,   bad areas:        0,        run time:      7m 39s
pct rescued:   30.00%, read errors:        0,  remaining time:      2m 23s
                              time since last successful read:         n/a
Copying non-tried blocks... Pass 1 (forwards) 
ddrescue: Write error: No space left on device

```
念のため sync 3回行うおまじない

```

$ sync
$ sync
$ sync
```

# GParted でパーティションを変更

ディスク論理サイズはこれまでの操作で 100GiB →  30GiB となっている。しかしながらパーティーション構成は最初の 10GiB 時のままだったのでディスク論理サイズに合わせて拡張する。

今回は CD 起動 Ubuntu のままで、GParted を使って操作。

起動すると未割り当てが20GiB ある。 /dev/sda5 を増やしたいのだが、それは extended 領域としての /dev/sda2 中に存在しているのがわかる。なのでまずは /dev/sda2 を増やす。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/8f1e1bd4-8d47-1c1e-0192-f9d636ca6bf6.png)

うまいくいったら更に /dev/sda5  を増やす。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ac5fcca4-68f8-7fc4-30eb-3c4ba18be37b.png)

書き込んだ後、電源をOff, CDイメージを解除して 30GiB のディスクイメージから起動。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1f111ec4-aded-654b-ddca-9751e89b74c4.png)

うまく起動できました

# おまけ 起動しなくなった本当の原因

論理サイズ 10GiB のディスクイメージを 100GiB に変更して起動しなくなったような気がしていたが、原因はそれ以前にあった。 10GiB 時にXojoをインストールして容量が足りなくなったのだが、一度電源OFF → 論理ディスクサイズ拡張 → パーティーションサイズ拡張せず起動としたため、空き領域がゼロで起動できなかったのが原因でした。

なので、起動しなかった 100GiB のディスクイメージも、CD起動していらないファイルを削除して空き領域を確保したら起動しました。

また、論理ディスクサイズ拡張とパーティーションサイズ拡張のコンボでも起動するはずですね。
他のディスクサイズでのケースで同様の事態になった時にこのやりかたでクリアしました。