StupidDog's blog

IT関連の手近な所で、疑問に思った事を調べた記録

「Vagrantの裏方では何が作られているのか?」

はじめに

Vagrant仮想マシンを作成しつつRuby on Rails開発環境を構築していました。
Vagrantの本家サイトのガイドに従って作成していたのですが、各コマンドが自分の環境にどんな変化を与えるのかが知りたくなりました。
コマンドで状態を確認する方法はあるのですが、どこに何のファイルが、いつ作られるのかが気になり、作成されるファイルを中心に調べてみた結果が以下の通りです。

概要

環境
software version
Ubuntu(ホストOS) 12.10 LTS 32bit
Ubuntu(ゲストOS) 13.10 Server 32bit
VirtualBox 4.3.6.r91406
Vagrant 1.4.3
項目
  1. "vagrant box add"は何をする?
  2. "vagrant init"は何をする?
  3. "vagrant up"は何をする?
  4. おまけ

1."vagrant box add"は何をする?

$ vagrant box add <name> <url>

このコマンドで、論理名とBOXファイルの場所(ローカルならパス,リモートならURL)を指定してBOXファイルを追加する。
追加するとはどうなることか、論理名ってなんの名前か?

BOXファイルは仮想マシンのひな型となるファイルを配布可能な状態にまとめたものです。
vagrantは、まとめられたBOXファイルから直接には仮想マシンを作成しません。
一度、ローカルへ展開してキャッシュしたものを使います。
指定した論理名とは、このキャッシュしたBOXファイルを識別するために付ける名前です。

キャッシュされているBOXファイルはどこに保存されているのか?
「~/.vagrant.d/boxes」以下にディレクトリが作成されて保存されます。

実際に実行して結果を確認すると、<name>/<provider>*1でサブディレクトリが作成されてBOXファイルの中身が展開されているのが分かります。

stupiddog@pc02:~$ vagrant box add ubuntu1310 ~/Downloads/box/ubuntu-1310-i386-virtualbox-puppet.box
Downloading box from URL: file:/home/stupiddog/Downloads/box/ubuntu-1310-i386-virtualbox-puppet.box
Extracting box...te: 59.0M/s, Estimated time remaining: 0:00:01)
Successfully added box 'ubuntu1310' with provider 'virtualbox'!

stupiddog@pc02:~$ tree -aFh ~/.vagrant.d/boxes
/home/stupiddog/.vagrant.d/boxes/
└── [4.0K]  ubuntu1310/
    └── [4.0K]  virtualbox/
        ├── [ 258]  Vagrantfile
        ├── [ 11K]  box.ovf
        ├── [ 120]  info.json
        ├── [  26]  metadata.json
        └── [400M]  ubuntu1310-i386-disk1.vmdk

2 directories, 5 files

stupiddog@pc02:~$ vagrant box list
ubuntu1310 (virtualbox)

※ BOXファイルは毎回ネットから取得すると大変なので、先にダウンロードしています。

2."vagrant init"は何をする?

仮想マシンを作成するための準備をします…何をするの?
設定ファイル(Vagrantfile)のひな型を、このコマンドを実行したカレントディレクトリに作成します。
なので、管理単位で新規にディレクトリを作成して実行します。

実行した結果が以下の通りです。

stupiddog@pc02:~$ mkdir -p ~/vm/z001; cd ~/vm/z001
stupiddog@pc02:~/vm/z001$ ls -a
.  ..
stupiddog@pc02:~/vm/z001$ vagrant init ubuntu1310
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

stupiddog@pc02:~/vm/z001$ tree -aFh ~/vm/z001
/home/stupiddog/vm/z001
└── [4.5K]  Vagrantfile

0 directories, 1 file

まだ、この段階では仮想マシンは構築されていません。
VirtualBox仮想マシンは、「~/VirtualBox VMs/」以下にサブディレクトリが作成されて保存されます。

stupiddog@pc02:~/vm/z001$ vboxmanage list vms
stupiddog@pc02:~/vm/z001$

stupiddog@pc02:~/vm/z001$ tree -aFh ~/VirtualBox VMs/
/home/stupiddog/VirtualBox VMs/

0 directories, 0 files

stupiddog@pc02:~/vm/z001$ vagrant status
Current machine states:

default                   not created (virtualbox)

The environment has not yet been created. Run `vagrant up` to
create the environment. If a machine is not created, only the
default provider will be shown. So if a provider is not listed,
then the machine is not created for that environment.

んむ、"not created"です。

3."vagrant up"は何をする?

このコマンドの初回起動時に、仮想マシンが構築されます。
"vagrant init <name>"で作成した設定ファイルの「config.vm.box=<name>」から、ひな型にするBOXファイルのキャッシュを決定して仮想マシンを構築します。

実行した結果が以下の通りです。

stupiddog@pc02:~/vm/z001$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'ubuntu1310'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for machine to boot. This may take a few minutes...
[default] Machine booted and ready!
[default] Mounting shared folders...
[default] -- /vagrant

stupiddog@pc02:~/vm/z001$ vagrant status
Current machine states:

default                   running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

stupiddog@pc02:~/vm/z001$ vboxmanage list vms
"z001_default_1392779981693_33350" {52c768b7-4c06-4a1e-95a1-0b7d885bbdac}

stupiddog@pc02:~/vm/z001$ tree -aFh ~/VirtualBox VMs/
/home/stupiddog/VirtualBox VMs/
└── [4.0K]  z001_default_1392779981693_33350/
    ├── [4.0K]  Logs/
    │   └── [ 42K]  VBox.log
    ├── [1.2G]  ubuntu1310-i386-disk1.vmdk
    ├── [7.6K]  z001_default_1392779981693_33350.vbox
    └── [7.6K]  z001_default_1392779981693_33350.vbox-prev

2 directories, 4 files

stupiddog@pc02:~/vm/z001$ tree -aFh ~/vm/z001/
/home/stupiddog/vm/z001/
├── [4.0K]  .vagrant/
│   └── [4.0K]  machines/
│       └── [4.0K]  default/
│           └── [4.0K]  virtualbox/
│               ├── [  10]  action_provision
│               ├── [  10]  action_set_name
│               └── [  36]  id
└── [4.5K]  Vagrantfile

4 directories, 4 files

カレントディレクトリに管理用の隠しディレクトリ(.vagrant)が作成されています。
また、仮想マシンのファイルも「~/VirtualBox VMs/」に作成されています…仮想マシンの名前にカレントディレクトリ名が付いていますね。

4.おまけ

作成した結果は分かったので、削除した結果も追ってみました。

ひな型から構築した仮想マシンより先に、キャッシュされているBOXファイルを消すと仮想マシンの削除が Vagrantからできなくなるので注意です

2014.2.27 訂正
"vagrant destroy"による削除時に、元になったBOXファイルがなくても仮想マシンの削除できました。検証ミスです。

まず、仮想マシンを削除します。
「~/VirtualBox VMs/」以下にあった仮想マシンのディレクトリが削除されています。
"vagrant status"の結果も"no created"になってますが、カレントの管理用ディレクトリは残ってます。

[default] Attempting graceful shutdown of VM...
stupiddog@pc02:~/vm/z001$ vagrant destroy
Are you sure you want to destroy the 'default' VM? [y/N] y
[default] Destroying VM and associated drives...

stupiddog@pc02:~/vm/z001$ vagrant status
Current machine states:

default                   not created (virtualbox)

The environment has not yet been created. Run `vagrant up` to
create the environment. If a machine is not created, only the
default provider will be shown. So if a provider is not listed,
then the machine is not created for that environment.

stupiddog@pc02:~/vm/z001$ vboxmanage list vms 
stupiddog@pc02:~/vm/z001$ 

stupiddog@pc02:~/vm/z001$ tree -aFh ~/VirtualBox VMs/
/home/stupiddog/VirtualBox VMs/

0 directories, 0 files

stupiddog@pc02:~/vm/z001$ tree -aFh ~/vm/z001/
/home/stupiddog/vm/z001/
├── [4.0K]  .vagrant/
│   └── [4.0K]  machines/
│       └── [4.0K]  default/
│           └── [4.0K]  virtualbox/
└── [4.5K]  Vagrantfile

4 directories, 1 file

次に、キャッシュしているBOXファイルを削除します。
結果は「~/.vagrant/boxes」以下に作成されてたサブディレクトリは残り中身だけが削除されました。
でも、"vagrant box list"コマンドでリストされないので、実行時に見ているのはディレクトリの有無だけではないようです。

stupiddog@pc02:~/vm/z001$ vagrant box remove ubuntu1310
Removing box 'ubuntu1310' with provider 'virtualbox'...

stupiddog@pc02:~/vm/z001$ vagrant box list
There are no installed boxes! Use `vagrant box add` to add some.

stupiddog@pc02:~/vm/z001$ tree -aFh ~/.vagrant.d/boxes/
/home/stupiddog/.vagrant.d/boxes/
└── [4.0K]  ubuntu1310/

1 directory, 0 files
さて、キャッシュのBOXファイルが無い状態で"Vagrant up"をしたらどうなるか?

当然、エラーとなります。

stupiddog@pc02:~/vm/z001$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
There are errors in the configuration of this machine. Please fix
the following errors and try again:

vm:
* The box 'ubuntu1310' could not be found.

しかし、設定ファイルの「Vagrantfile」にある「config.vm.box_url」パラメータを有効にして<url>を設定すると"vagrant up"の実行時にBOXファイルの追加を行い仮想マシンの構築まで行ってくれます。

VAGRANTFILE_API_VERSION = "2"
 
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu1310"
  config.vm.box_url = "~/Downloads/box/ubuntu-1310-i386-virtualbox-puppet.box"
end

設定ファイルを上記の設定にしてから"vagrant up"を実行した結果が以下の通りです。

stupiddog@pc02:~/vm/z001$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Box 'ubuntu1310' was not found. Fetching box from specified URL for
the provider 'virtualbox'. Note that if the URL does not have
a box for this provider, you should interrupt Vagrant now and add
the box yourself. Otherwise Vagrant will attempt to download the
full box prior to discovering this error.
Downloading box from URL: file:/home/stupiddog/Downloads/box/ubuntu-1310-i386-virtualbox-puppet.box
Extracting box...te: 59.7M/s, Estimated time remaining: --:--:--)
Successfully added box 'ubuntu1310' with provider 'virtualbox'!
[default] Importing base box 'ubuntu1310'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for machine to boot. This may take a few minutes...
[default] Machine booted and ready!
[default] Mounting shared folders...
[default] -- /vagrant

stupiddog@pc02:~/vm/z001$ vboxmanage list vms
"z001_default_1392781885035_69804" {bfe3c1d7-a02e-405a-ad0d-10d8b9094463}

stupiddog@pc02:~/vm/z001$ tree -aFh ~/VirtualBox VMs/
/home/stupiddog/VirtualBox VMs/
└── [4.0K]  z001_default_1392781885035_69804/
    ├── [4.0K]  Logs/
    │   └── [ 42K]  VBox.log
    ├── [1.2G]  ubuntu1310-i386-disk1.vmdk
    ├── [7.6K]  z001_default_1392781885035_69804.vbox
    └── [7.6K]  z001_default_1392781885035_69804.vbox-prev

2 directories, 4 files
stupiddog@pc02:~/vm/z001$ vagrant box list
ubuntu1310 (virtualbox)
stupiddog@pc02:~/vm/z001$ tree -aFh ~/.vagrant.d/boxes/
/home/stupiddog/.vagrant.d/boxes/
└── [4.0K]  ubuntu1310/
    └── [4.0K]  virtualbox/
        ├── [ 258]  Vagrantfile
        ├── [ 11K]  box.ovf
        ├── [ 106]  info.json
        ├── [  26]  metadata.json
        └── [400M]  ubuntu1310-i386-disk1.vmdk

2 directories, 5 files

仮想マシンのファイルだけでなく、BOXファイルのキャッシュも作成されています。
この方法が、「vagrant init 」で作成した設定ファイルからの仮想マシン構築の動作と同じになります。
キャッシュが既にある場合は、BOXファイルの追加は行われません。

まとめ

"vagrant box add"や"vagrant init"、"vagrant up"が何をするために何を作るのかが分かりました。
仮想マシン構築までにローカルに作成されるファイルが明確になったので、意識しながらコマンドを実行できます。
また、使わなくなったキャッシュは消した方が良さそうですね。
今回は、vagrantのソースを覗いてて見つけたファイルの処理を確認しました。
やっぱり自分が使う道具の理解度があがると落ち着きます。

補足

仮想マシン作成のために利用したBOXファイルは、Puppet Labsで公開しているpuppet導入済みのものです。
Puppet Vagrant Boxes

*1:vagrantでは仮想マシンの環境を提供しているものをproviderと呼んでます。VirtualBoxVMWareなど