VagrantでVirutalBoxとHyper-Vの同時利用

# TL;DR

vagrant 配下で VirtualBox Provider と Hyper-V Provider が同時に使えたのでそのメモです。

# はじめに

これまで Windows 11 Home + Vagrant + VirtualBox でまあまあ幸せに暮らしてきたんですが、仕事で Hyper-V を触らないといけない状況になったので、会社から余っているライセンスを分けてもらって Windows 11 Pro にアップグレードしました。

その後、まずは [Hyper-Vとサードパーティー製仮想マシン環境を共存させる](https://atmarkit.itmedia.co.jp/ait/articles/2107/29/news021.html) を読んでみて、上っ面だけ理解した気になりました。

ただ、このページでは対象が Windows 10 なのと、自分には不要な部分も多かったので、情報の整理を兼ねて自分の環境の棚卸しをしてみた次第です。以下、補足説明等は、ほぼほぼこのページの内容を抜粋したものです。

# バージョン等

- Note PC H/W : CPU i7-9750H @ 2.6GHz, RAM 16GB
- Windows 11 Pro 21H2 220000.613 (Windows 11 Home からのアップグレード）
- Vagrant 2.2.19
- VirtualBox 6.1.34

# Windows の機能の有効化または無効化

[コンパネ]＞[プログラム]＞[プログラムと機能]＞[Windows の機能の有効化または無効化] にある機能のうち、仮想化に関係ありそうなものを列挙してみました。手元の環境では (*1)(*2)を除き、すべて無効化されていました。

├┬ Hyper-V
│├┬ Hyper-V プラットフォーム
││├─ Hyper-V Hypervisor
││└─ Hyper-V サービス
│└┬ Hyper-V 管理ツール
│　├─ Hyper-V GUI 管理ツール
│　└─ Windows PowerShell 用 Hyper-V モジュール
├─ Linux 用 Windows サブシステム (*1)
├─ Windows サンドボックス
├─ Windows ハイパーバイザー プラットフォーム
├─ コンテナー
├─ 仮想マシン プラットフォーム (*2)
├─ 保護されたホスト

(*1)‥（WSL を入れていたから？）もともと有効化されていました。
(*2)‥WSL2 を入れたら自動的に有効化されました。

なお WSL / WSL2 についてはほとんど活用できていません。たまに Windows 側のファイルを grep とか find できそうかなと触ってみたりする程度です。

# 表示されるヘルプ

[Windows の機能の有効化または無効化] でマウスオーバーすると表示される、機能の概要説明を記載してみました。正直よくわからないものもあります。★は補足説明です。

- Hyper-V 
  - 仮想マシンおよびそのリソースを作成および実行するためのサービスおよび管理ツール
  - ★Windows OS の (Type 1) ハイパーバイザー機能は「Windows ハイパーバイザー」として分離された
- Hyper-V プラットフォーム
  - 仮想マシンとそのリソースを作成および管理に使用できるサービス
- Hyper-V Hypervisor
  - Hyper-V Hypervisor
- Hyper-V サービス
  - 仮想マシンとそのリソースを作成および管理に使用できるサービス
- Hyper-V 管理ツール
  - Hyper-V を管理する GUI およびコマンドラインツール
- Hyper-V GUI 管理ツール
  - Hyper-V マネージャー スナップインおよび仮想マシン接続ツール
- Windows PowerShell 用 Hyper-V モジュール
  - Hyper-V を管理する Windows PowerShell コマンドレット
- Linux 用 Windows サブシステム
  - ネイティブなユーザー モードの Linux シェルおよびツールを Windows で実行するためのサービスと環境
- Windows サンドボックス
  - Windows サンドボックスのシナリオ実行に必要な依存関係
- Windows ハイパーバイザー プラットフォーム
  - 仮想化ソフトウェアを Windows ハイパーバイザー で実行できるようにする
- コンテナー
  - Windows Server コンテナーとそのリソースを作成して管理するためのサービスとツール
- 仮想マシン プラットフォーム
  - 仮想マシンのプラットフォーム サポートの有効化
- 保護されたホスト
  - デバイスを有効にして、リモート構成証明を使うシールドされた仮想マシンを作成して実行

# Windows ハイパーバイザーとは

前述の Web ページにあった「Windows ハイパーバイザー」がキモになるようなので、それについての補足説明です。ちなみにこの名前は「Windowsの機能の有効化または無効化」には出てきません。

- Hyper-Vの仮想マシン管理機能をAPIとして公開するもの
- Windowsカーネルより先に起動する（このため無効化の際はリブートが必要）
- Type 2 HyperVisor（VirtualBox, VMware WorkStation等）がこれに対応することで、Hyper-V との共存が可能になった
- 当該機能に依存する機能は以下の通り：
    - Windows Subsystem for Linux Ver.2(WSL 2)
    - Windows サンドボックス
    - Windows Defender Application Guard
    - Virtualization Based Sevurity(VBS)
    - Hypervisor-Protected Code Integrity(HVCI) / Memory Integrity
- Windows 10/11 Home エディションでも動作している可能性ありとのこと

# 機能の追加

「Hyper-V 配下で動く仮想マシンと VirutualBox 配下で動く仮想マシンが同時に動かせるのか」を試すために、以下の機能を有効化しました。Hyper-V の有効化にはリブートを求められます。

- Windows ハイパーバイザー プラットフォーム
- Hyper-V 配下すべて

# 動作確認

リブート後、Windows ハイパーバイザー プラットフォームが有効になっていることを確認します。ちなみにこれらは PowerShell を管理者権限で起動しないと正しく動作しません。

```
PS> bcdedit /enum `{current`} | grep hypervisorlaunchtype
hypervisorlaunchtype    Auto
```

さらに Hyper-V が有効になっていることを確認。

```
PS> Get-WindowsOptionalFeature -online -FeatureName hypervisor*
FeatureName      : HypervisorPlatform
DisplayName      : Windows ハイパーバイザー プラットフォーム
Description      : 仮想化ソフトウェアを Windows ハイパーバイザーで実行できるようにします
RestartRequired  : Possible
State            : Enabled
CustomProperties : 
```

念のため、この状態で vagrant up で VitualBox ベースの仮想マシンが問題なく起動することを確認しました。ちなみに [Vagrant - Hyper-V](https://www.vagrantup.com/docs/providers/hyperv) には

> Warning: Enabling Hyper-V will cause VirtualBox, VMware, and any other 
> virtualization technology to no longer work. See this blog post for an 
> easy way to create a boot entry to boot Windows without Hyper-V enabled, 
> if there will be times you will need other hypervisors.

といった恐ろしげなことが書いてあるのですが、今は状況が変わったということなのかな？Intel CPU だから OK なのかな？

念のため VitualBox ベースの仮想マシンの方は vagrant halt しておき、その後、適当なディレクトリに移動して、Hyper-V ベースの仮想マシンの起動にチャレンジしてみました。

```
PS> vagrant box add --provider hyperv centos/7
PS> vagrant box list | grep hyperv
centos/7            (hyperv, 2004.01)
PS> vim Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.define "hv_test1" do |hv_test1|
    hv_test1.vm.box = "centos/7"
    hv_test1.vm.hostname = "hv-test1"
  end
end
```

さて、準備ができたので起動してみます。
```
PS> vagrant up --provider=hyperv
The provider 'hyperv' that was requested to back the machine
'hv_test1' is reporting that it isn't usable on this system. The
reason is shown below:

The Hyper-V provider requires that Vagrant be run with
administrative privileges. This is a limitation of Hyper-V itself.
Hyper-V requires administrative privileges for management
commands. Please restart your console with administrative
privileges and try again.
```
PowerShell を「管理者で実行」しないとダメらしい。

前述のページによると、Hyper-V （のベースになっている Windows ハイパーバイザー）は、VirtualBox 等と異なり Type 1 Hypervisor らしいので、この制限は仕方なさそう。改めて PowerShell 管理者で実行してみました。

```
PS C:\Users\hotta\vm\hyperv> vagrant up --provider=hyperv
Bringing machine 'hv_test1' up with 'hyperv' provider...
==> hv_test1: Verifying Hyper-V is enabled...
==> hv_test1: Verifying Hyper-V is accessible...
==> hv_test1: Importing a Hyper-V instance
    hv_test1: Creating and registering the VM...
    hv_test1: Successfully imported VM
    hv_test1: Configuring the VM...
    hv_test1: Setting VM Enhanced session transport type to disabled/default (VMBus)
==> hv_test1: Starting the machine...
==> hv_test1: Waiting for the machine to report its IP address...
    hv_test1: Timeout: 120 seconds
    hv_test1: IP: 172.29.55.23
==> hv_test1: Waiting for machine to boot. This may take a few minutes...
    hv_test1: SSH address: 172.29.55.23:22
    hv_test1: SSH username: vagrant
    hv_test1: SSH auth method: private key
    hv_test1:
    hv_test1: Vagrant insecure key detected. Vagrant will automatically replace
    hv_test1: this with a newly generated keypair for better security.
    hv_test1:
    hv_test1: Inserting generated public key within guest...
    hv_test1: Removing insecure key from the guest if it's present...
    hv_test1: Key inserted! Disconnecting and reconnecting using new SSH key...
==> hv_test1: Machine booted and ready!
==> hv_test1: Setting hostname...
==> hv_test1: Running provisioner: shell...
    hv_test1: Running: inline script
```
おお、動いた。心なしか VirtualBox Provider より起動が早い気がする（気のせい？）
Hyper-V の制限により、静的 IP アドレスの割り当てはできず自動的に NAT 構成になるとのこと。付与された IP アドレスがメッセージ中に見えます。

```
PS C:\Users\hotta\vm\hyperv> vagrant ssh
[vagrant@hv-test1 ~]$ cat /etc/centos-release
CentOS Linux release 7.8.2003 (Core)            
```

ログインも問題ないようです。

その後、懸案の VirtualBox Provider との同時起動ですが、これも無事に動きました。もちろん VirtualBox Provider の方は、通常の（管理者ではない） PowerShell から起動可能でした。

```
PS C:\Users\hotta\vm\brms> vagrant global-status | grep running
897d3ca  vb_test1 virtualbox running  C:/Users/hotta/vm/vbox
c604dbe  hv_test1 hyperv     running  C:/Users/hotta/vm/hyperv
```