CentOS 7のHyper-V provider用boxを作成、運用する

# 概要
VagrantのHyper-V用boxを作成、運用する。ゲストOSはCentOS 7とする。
# Hyper-V用のboxを作成する
Hyper-V マネージャーで以下の構成の仮想マシンを作成する。

<table>
  <tr>
    <th colspan="2">名前</th>
    <td>何でも良いがここではCentOS-7.0-x86_64-minimalとする。</td>
  </tr>
  <tr>
    <th colspan="2">仮想マシンの世代</th>
    <td>第2世代</td>
  </tr>
　　<tr>
    <th colspan="2">ハードディスク</th>
    <td>127GB</td>
  </tr>
  <tr>
    <th rowspan="3">メモリ</th>
    <th>動的メモリ</th>
    <td>使用する</td>
  </tr>
  <tr>
    <th>スタートアップ RAM</th>
    <td>768MB</td>
  </tr>
  <tr>
    <th>最小 RAM</th>
    <td>512MB</td>
  </tr>
  <tr>
    <th colspan="2">ファームウェア</th>
    <td>セキュアブート有効のチェックを外す</td>
  </tr>
</table>

# CentOSのインストール
CentOSについてはnetinstallかminimalのISOをダウンロードしてインストールする。
細かい手順については割愛するが、rootのパスワードをvagrantとすることと、ユーザvagrantを作成してこちらのパスワードもvagrantとすることがポイント。

# 仮想OS上での作業
CentOSをインストールしたらrootでログインして以下の作業を行う。
なお、この項で示すコマンドの先頭にある#や$はプロンプトなので入力する必要はない。
例えば
<pre># ls</pre>
と記載してある場合、rootユーザでlsコマンドを実行するという意味であって、# lsと入力するわけではない。

## インストールされたパッケージの最新化
シェル上で
<pre># yum update</pre>
としてインストールされたパッケージを最新化する。

## sudoersファイルの編集
シェル上で

<pre># visudo</pre>
として、sudoersファイルに下記内容を追記する。
<pre>Defaults:vagrant !requiretty
vagrant ALL=(ALL) NOPASSWD: ALL</pre>

## sshdの設定
/etc/ssh/sshd_configを編集して、
UseDNSをnoに、PubkeyAuthenticationをyesに変更する。

## Hyper-V Key-Value Pair(KVP) daemonのインストールと自動起動設定
Hyper-V マネージャがゲストのIPアドレスを取得できるよう、Hyper-V KVP daemonをインストールする。
シェル上で、

<pre># yum install hypervkvpd</pre>

とすることでインストールできる。デフォルトでhypervkvpdはOS起動時に自動起動するようになっているが、もしなっていない場合は
<pre># systemctl enable hypervkvpd</pre>
として自動起動するよう設定する。

## カーネルパラメータの編集
[Best Practices for running Linux on Hyper-V](https://technet.microsoft.com/en-us/library/dn720239.aspx "TechNet")にある通りカーネルパラメータを変更する。
より具体的には/etc/default/grubを編集し、GRUB_CMDLINE_LINUXの末尾にnuma=off elevator=noopを追加する。
/etc/default/grubの編集が終わったらシェル上で
<pre># /sbin/grub2-mkconfig -o /etc/grub2-efi.cfg</pre>
として、編集内容をgrubに反映させる。

## 初回vagrant up用のSSH公開鍵の取得
1回目のvagrant upのためにSSH公開鍵を取得する。

<pre># su - vagrant
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ curl -o ~/.ssh/authorized_keys https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub
$ chmod 600 ~/.ssh/authorized_keys
$ exit</pre>

上記で取得した公開鍵に対応する秘密鍵は
[Githubのリポジトリ](https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant)上にある。
この秘密鍵はOpenSSH用のため、Puttyで使用するためにはputtygenで変換する必要があることに注意。

## 一旦再起動
ここまで終わったらシェル上で
<pre># shutdown -r now</pre>
としてゲストOSを一旦再起動する。再起動したら前述した秘密鍵で仮想マシンにSSHでログインしてみる。
無事SSHでログインできたら、そのままSSHで続きの作業を行う。

## yumのキャッシュ削除
仮想ハードディスクの容量削減のため、
<pre>$ sudo yum clean all</pre>
としてyumのキャッシュを削除する。

## コマンド履歴の消去
必ずしも必要な作業ではないが、box作成時のコマンド履歴を消しておきたいときにはシェル上で以下のようにする。
<pre>$ unset HISTFILE
$ echo -n > ~/.bash_history
$ sudo sh -c "echo -n > /root/.bash_history"</pre>

## ゲストOSのシャットダウン
ここまでくればゲストOS上での作業は終わりなので、シェル上で
<pre>sudo shutdown -h now</pre>
としてゲストOSをシャットダウンする。

# Windows上での作業

## 仮想マシンのエクスポート
Hyper-V マネージャで仮想マシンをエクスポートする。
ここではエクスポート先をC:\tmp\boxとする。

## boxを構成するファイルの準備
エクスポートが完了したら、エクスポート先のSnapshotsフォルダを削除する。
次にエクスポート先のVirtual Hard Disks, Virtual Machinesフォルダがある階層で、metadata.jsonファイルを以下の内容で作成する。
"name"は何でも良い(無くても良い)が、"provider": "hyperv"は必要なので必ず記述する。

<pre>{
    "name": "no17/centos-7.0-x86_64-minimal-hyperv",
    "provider": "hyperv"
}</pre>

## boxファイルの作成
エクスポート先のVirtual Hard Disks, Virtual Machinesフォルダ、metadata.jsonファイルがある階層をルートとしてzipで圧縮する。圧縮したファイルの拡張子は.boxとする。
ここではC:\tmp\box\centos-7.0-x86_64-minimal-hyperv.boxとする。

## Vagrantのスクリプトの修正
Vagrantのバージョン1.7.1ではboxのセキュアブート設定が無視されてしまうため、そのままでboxが起動しない。
最新版のVagrantで対応されるまで、[Vagrantのリポジトリにコミットされた修正](https://github.com/tomassrnka/vagrant/commit/21e2f33fb0e6ed9acd23f279b2806d0d9761e609)を基に<Vagrantのインストール先ディレクトリ>/embedded/gems/gems/vagrant-1.7.1/plugins/providers/hyperv/scripts/import_vm.ps1に以下の記述を追加する。

<pre># Determine secure boot options
$secure_boot_enabled = (Select-Xml -xml $vmconfig -XPath "//secure_boot_enabled").Node."#text"
# Set EFI secure boot 
if ($secure_boot_enabled -eq "True") {
    Set-VMFirmware -VM $vm -EnableSecureBoot On
}  else {
    Set-VMFirmware -VM $vm -EnableSecureBoot Off
}</pre>

## boxの追加と起動

管理者権限で起動したコマンドプロンプト、またはPowershellで

<pre>vagrant box add no17/centos-7.0-x86_64-minimal-hyperv \box\centos-7.0-x86_64-minimal-hyperv.box
vagrant init no17/centos-7.0-x86_64-minimal-hyperv
vagrant up --provider hyperv</pre>
とすることで起動させることができる。
初回起動時には仮想マシンのネットワークアダプタをHyper-Vのどの仮想ネットワークアダプタに紐付けるか決めるよう促される他、SSH公開鍵が新たに生成されたものに置き換えられる。
生成されたSSH公開鍵に対応する秘密鍵は<Vagrantfileがあるフォルダ>\.vagrant\machines\default\hypervにprivate_keyという名前で保存されている。
この秘密鍵はOpenSSH形式なので、Puttyで使用する場合にはputtygenで変換する必要がある。
また、初回起動時に限らず毎回ホストとゲスト間でのフォルダ共有のためWindowsにログインするためのユーザ名とパスワードを尋ねられるので注意。