vagrant
sahara

Vagrant Saharaのcommitせずoffしたら元に戻るという誤解

More than 3 years have passed since last update.


Vagrant Saharaについて

saharaはvagrant上で使えるプラグインです。

ご存知の通りゲストOSの状態をお試し設定した後、元の状態にロールバックするっていうことが可能になります。

jedi4ever/sahara


CommitせずにOffったら元に戻るんでしょっていう誤解

saharaに関して知識もなかったので当然いろんな紹介記事をみて使ってみました。

Googleで検索したいくつかのサイトにcommitしていないものはoffした時点で消える

ような記述があったのでそれを鵜呑みにして以下のようにやってみました。

# sahara開始

host$ vagrant sandbox on

# 仮想マシン起動
host$ vagrant up

# 仮想マシン接続して色々設定
host$ vagrant ssh
guest$ touch hoge
guest$ ls
hoge
guest$ exit

# ここでcommitせずにoffすれば元の環境に戻ると思ってた
host$ vagrant off

# 結果を確認してみる
host$ vagrant ssh
guest$ ls
hoge

あっるぅぇぇ〜?

offしたあとで中を覗いてみるとバッチリ情報が残っていますね。

おかしい、Google上位サイトにいくつも記述があったのだから間違っていないはず

きっと何か操作抜け漏れや間違いがあったのかなと思っていろいろ調べても

よくわかんない。

でもこんな記事もありました。


コミットせずにsandboxをoffにするとcommitされたことになるっぽい.



なにが正しいのかわからなくなってきたのでソースを読んでみる。


saharaのディレクトリ構造

saharaはこんな感じのシンプルな構造です。

$tree sahara

sahara
├── Gemfile
├── README.md
├── Rakefile
├── lib
│   ├── sahara
│   │   ├── command
│   │   │   ├── commit.rb
│   │   │   ├── off.rb
│   │   │   ├── on.rb
│   │   │   ├── rollback.rb
│   │   │   ├── root.rb
│   │   │   └── status.rb
│   │   ├── errors.rb
│   │   ├── session
│   │   │   ├── factory.rb
│   │   │   ├── libvirt.rb
│   │   │   ├── parallels.rb
│   │   │   ├── virtualbox.rb
│   │   │   └── vmware.rb
│   │   └── version.rb
│   └── sahara.rb
├── locales
│   └── en.yml
└── sahara.gemspec

どうもlib/sahara/sessionに仮想化ソフト毎の処理が記述されていて

それをlib/sahara/command内のコマンドが1枚ラッパーとしてかぶさって

仮想化ソフトの違いを意識することなくon/off/rollbackなどをできるようになるらしい。


virtualboxでのoff時の挙動を見てみる

使っているのはvirtualboxだったのでlib/sahara/session/virtualbox.rbを覗いてみる

ここから見れます

#大事なとこだけ抜粋

def off
`#{@vboxcmd} snapshot "#{@instance_id}" delete "#{@sandboxname}" `
end

def on
`#{@vboxcmd} snapshot "#{@instance_id}" take "#{@sandboxname}" --pause`
end

def commit
`#{@vboxcmd} snapshot "#{@instance_id}" delete "#{@sandboxname}"`
`#{@vboxcmd} snapshot "#{@instance_id}" take "#{@sandboxname}" --pause`
end

まとめると、

- onの時は特定のスナップショットを作成する

- offの時は特定のスナップショットを削除する

- commitの時は特定のスナップショットを削除した上で特定のスナップショットを作成する

commitはつまりoff+onということになりますね

commitの動作が状態を保存することだとすると、offかonかのどちらかで状態を保存しなければなりませんが、この場合どう考えてもoffでやっていると思われます。

つまりスナップショットを削除しても状態は保存されている!ということになります。

ということはこの時点でoffすると状態が元に戻るっていう諸説は間違っているということになりますね。


解析結果:offするとcommit(off+on)時同様状態は保存されます。


なんでこうなった!

実はvirtualboxでスナップショットを多用していたのでここはすんなり納得出来ました。

そもそもsaharaなど使わずvirtualboxで手動でスナップショットをとって、削除をしてみたらすぐわかります。

削除するとそのスナップショットだけが完全になくなるのではなく、前後(どちらか不明)のスナップショットに内容がマージされるのです。

それもそのはず。

スナップショットは毎回差分だけを持っていますが、複数スナップショットがあって途中のスナップショットが完全になくなってしまってはそれ以前のスナップショットが無駄になってしまいます。

そのため削除するときには前後のスナップショットどちらかに情報をマージした上で目的のスナップショットを削除しているのですね。


結論;元に戻したいならかならずrollbackしてからoffしましょう

ということでoffで状態は元に戻りません。

以下のようにoff前にrollbackを必ずやりましょう。

$ vagrant sandbox on

$ vagrant sandbox up
$ vagrant sandbox ssh
・・・
# ここ重要
$ vagrant sandbox rollback
$ vagrant sandbox off

逆に重要そうなcommitなんてoffで代用できるので使う機会が半減します。

なんかいもこまめにon/offを繰り返しながら状態保存する必要がある場合にはcommitを使ったらコマンド数削減には役立つかもしれません。