Vagrantのゲストマシンを自動で再起動する

# 記事概要
`vagrant up`で起動したゲストマシンが、再起動を要求する場合があります。provisionの過程で`apt upgrade`などを行った場合などです。結局、ゲストマシンが利用可能になるのは`vagrant reload`で再起動を行った後になります。

この一連のプロセスを自動化する方法について書きます。`vagrant up`のコマンドのみで、即座に利用可能な仮想マシンが出来上がるべきなのです。

# 記事詳細
## 実行環境
`Windows 10 Home`
`Vagrant 2.2.4`
`ubuntu/bionic64 Official Ubuntu 18.04 LTS(Bionic Beaver)Daily Build`

## 自動化1:プラグインを使う

[Vagrant Reload Provisioner](https://github.com/aidanns/vagrant-reload)というプラグインを使う方法があります。

私はこの方法が最善であると思います。他の方法と異なり、provisionの任意のタイミングでゲストマシンを再起動出来るからです。プラグインを入れなければならないという欠点もありますが、それを遥かに上回る利点があるでしょう。

### インストール
下記のコマンドを入力するだけです。

```
vagrant plugin install vagrant-reload
```

詳しくは、[Vagrant Reload Provisioner](https://github.com/aidanns/vagrant-reload)をご覧ください。

### 使い方

`config.vm.provision "reload"`と書くだけです。
そのタイミングで`vagrant reload`されます。
以下が実例です。

```
Vagrant.configure("2") do |config|
  # 利用するVagrantBox
  config.vm.box = "ubuntu/bionic64"
  
  # プロビジョニング
  # パッケージの更新
  config.vm.provision "shell", inline: <<-SHELL
    apt update
    apt upgrade -y
  SHELL
  
  # 再起動
  config.vm.provision "reload"
end
```

また、任意のタイミングで`vagrant reload`することが出来ます。
以下が実例です。

```
Vagrant.configure("2") do |config|
  # 利用するVagrantBox
  config.vm.box = "ubuntu/bionic64"
  
  # ポートフォワード
  config.vm.network "forwarded_port", guest: 80, host: 8080
  
  # プロビジョニング
  # パッケージの更新
  config.vm.provision "shell", inline: <<-SHELL
    apt update
    apt upgrade -y
  SHELL
  
  # 再起動
  config.vm.provision "reload"
  
  # アパッチのインストール
  config.vm.provision "shell", inline: <<-SHELL
     apt install -y apache2
  SHELL
  
  # 再起動
  config.vm.provision "reload"
end
```

## 自動化2:Vagrantfileに再起動の処理を書く

Vagrantfileに再起動の処理を書く方法もあります。

以下のようなVagrantfileです。

~~~
Vagrant.configure("2") do |config|
  # 利用するVagrantBox
  config.vm.box = "ubuntu/bionic64"
  
  # プロビジョニング
  config.vm.provision "shell", inline: <<-SHELL
    apt update
    apt upgrade -y
  SHELL
  
  # 再起動
  config.trigger.after :up do |trigger|
    trigger.info = "Reloading..."
    trigger.run = { :inline => "vagrant reload" }
  end
end
~~~

通常、ゲストマシンが使えるのはゲストマシンの機能のみです。しかし、[Vagrant Triggers](https://www.vagrantup.com/docs/triggers/)の[run](https://www.vagrantup.com/docs/triggers/configuration.html#run)オプションはホストマシンの機能を使うことが出来るようです。この機能に依って、ホストマシンにゲストマシンを再起動させることが出来ます。

一方で、[Vagrant Triggers](https://www.vagrantup.com/docs/triggers/)は限定的なタイミングでしか呼び出すことが出来ません。provisionの任意のタイミングで呼び出すような挙動は出来ません。

従って、[Vagrant Reload Provisioner](https://github.com/aidanns/vagrant-reload)を用いた方法と比べると、柔軟性に欠く方法であることは否めません。

### ダメな例

**以下のようなVagrantfileは正常に動作しません。**

~~~
# ダメな例
Vagrant.configure("2") do |config|
  # 利用するVagrantBox
  config.vm.box = "ubuntu/bionic64"
  
  # プロビジョニング
  config.vm.provision "shell", inline: <<-SHELL
    apt update
    apt upgrade -y

    # ゲストマシンをゲストマシンから再起動
    reboot
  SHELL
end
~~~

ゲストマシンにゲストマシンを再起動させてはいけません。`reboot`や`shutdown -r now`などゲストマシンの機能で再起動させてはいけません。**ゲストマシンの共有フォルダが同期しなくなります。**
詳しくは、[Vagrantのゲストマシンを再起動すると共有フォルダが同期されない](https://qiita.com/flyingbarbarian/items/04c55ff16932597f1e07)をお読みください。

## 自動化3:Vagrantコマンドを呼び出すスクリプトを作る

Vagrantコマンドを呼び出すスクリプトを作成する方法もあります。則ち、`vagrant up`と`vagrant reload`を行う命令を書いたバッチファイルやシェルスクリプトを作成するのです。

以下のような簡潔なスクリプトです。

~~~
# ゲストマシンの起動
vagrant up
# ゲストマシンの再起動
vagrant reload
~~~

しかし、この方法はお薦め出来ません。Vagrantは『`vagrant up`を実行すれば、開発環境が自動で組みあがる』というコンセプトです。`vagrant up`を実行しても開発環境が出来上がらない俺ルールを作るのはコンセプトにそぐわないでしょう。それはVagrantを使う利点を損ねるものでしょう。

# 記事補足
この記事は、『[Vagrantのゲストマシンを再起動すると共有フォルダが同期されない](https://qiita.com/flyingbarbarian/items/04c55ff16932597f1e07)』という問題を回避しながら自動化しようという試みです。則ち、ゲストマシンにゲストマシンを再起動させるのではなく、ホストマシンにゲストマシンを再起動させるスクリプトを作ろうという試みです。その問題に関しては、[Vagrantのゲストマシンを再起動すると共有フォルダが同期されない](https://qiita.com/flyingbarbarian/items/04c55ff16932597f1e07)をお読みください。

また、その試みは下記のサイトで議論がなされていたので、興味のある方はご覧ください。

https://superuser.com/questions/1338429/how-do-i-reboot-a-vagrant-guest-from-a-provisioner

https://stackoverflow.com/questions/23894739/synced-folders-lost-when-rebooting-a-vagrant-machine-using-the-ansible-provision