vagrant-zz-multiprovider-snap 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ Vagrant Multi-Provder Snap
2
+ ==========================
3
+
4
+ Description
5
+ -----------
6
+
7
+ This Vagrant plugin provides a consistent interface to taking snapshots of
8
+ running Vagrant boxes. It currently supports the following providers:
9
+
10
+ * VirtualBox
11
+ * VMWare Fusion (via the commercial VMWare plugin)
12
+
13
+
14
+ Installation
15
+ ------------
16
+
17
+ The easiest way to install this plugin is via the published gem.
18
+
19
+ ```
20
+ vagrant plugin install vagrant-zz-multiprovider-snap
21
+ ```
22
+
23
+ (The 'zz' in the gem name is a workaround for a bug in Vagrant plugin loading
24
+ which prevents the mixins in this module from working correctly - we need to
25
+ force this plugin to be loaded after the vmware plugin otherwise this fails)
26
+
27
+
28
+ Usage
29
+ -----
30
+
31
+ Typical usage:
32
+
33
+ * Take a new snapshot
34
+ ```vagrant snap take [vm]```
35
+
36
+ * Roll back to the last snapshot
37
+ ```vagrant snap rollback [vm]```
38
+
39
+ * List snapshots
40
+ ```vagrant snap list [vm]```
41
+
42
+ Limitations
43
+ -----------
44
+
45
+ It's currently not possible to do any of the following:
46
+
47
+ * Give a custom snapshot name
48
+ * Roll back to a specific named snapshot
49
+ * Disable snapshotting
50
+
51
+ My own requirements don't include these features, but I could be tempted to
52
+ add them if anyone would find them useful.
53
+
54
+
55
+ Hacking
56
+ -------
57
+
58
+ Working on this module is a little tricky because of the obfuscation used by
59
+ the commercial VMWare module. The following approach should get you up and
60
+ running - although it's a bundler environment, you'll also need a packaged
61
+ Vagrant install in order to get access to the rgloader libraries.
62
+
63
+ ```
64
+ git@github.com:scalefactory/vagrant-multiprovider-snap.git
65
+ cd vagrant-multiprovider-snap
66
+ cp ~/.vagrant.d/license-vagrant-vmware-fusion.lic .
67
+ bundle install
68
+ bundle install --deployment
69
+ ```
70
+
71
+ You should now find that ```bundle exec vagrant status``` returns correctly,
72
+ and you can hack on the code from there.
73
+
74
+ Once you've made changes that you're happy with, I'd recommend using
75
+ ```rake build``` to create a gem, then installing that into your packaged
76
+ Vagrant install since some things which work in the bundler environment might
77
+ not work as expected in the packaged copy due to differences in how the plugins
78
+ are handled.
@@ -0,0 +1,54 @@
1
+ require 'optparse'
2
+ require 'vagrant'
3
+
4
+ module VagrantSnap
5
+
6
+ module Command
7
+
8
+ class List < Vagrant.plugin("2", :command)
9
+
10
+ def execute
11
+
12
+ options = {}
13
+
14
+ opts = OptionParser.new do |o|
15
+ o.banner = "Usage: vagrant snap list [vm-name]"
16
+ o.separator ""
17
+ end
18
+
19
+ argv = parse_options(opts)
20
+ return if !argv
21
+
22
+ results = []
23
+
24
+ with_target_vms(argv) do |machine|
25
+
26
+ results << "#{machine.name.to_s}"
27
+
28
+ snaps = machine.provider.driver.snapshot_list
29
+
30
+ if snaps.length == 0
31
+ results << " (none)"
32
+ else
33
+ snaps.each do |snap|
34
+ results << " + #{snap}"
35
+ end
36
+ end
37
+
38
+ results << "\n"
39
+
40
+ end
41
+
42
+ @env.ui.info(I18n.t("vagrant_snap.commands.list.output",
43
+ :snapshots => results.join("\n")),
44
+ :prefix => false)
45
+
46
+ 0
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,36 @@
1
+ require 'optparse'
2
+ require 'vagrant'
3
+
4
+ module VagrantSnap
5
+
6
+ module Command
7
+
8
+ class Rollback < Vagrant.plugin("2", :command)
9
+
10
+ def execute
11
+
12
+ options = {}
13
+
14
+ opts = OptionParser.new do |o|
15
+ o.banner = "Usage: vagrant snap rollback [vm-name]"
16
+ o.separator ""
17
+ end
18
+
19
+ argv = parse_options(opts)
20
+ return if !argv
21
+
22
+ with_target_vms(argv) do |vm|
23
+
24
+ vm.action(:snapshot_rollback)
25
+
26
+ end
27
+
28
+ 0
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,73 @@
1
+ require 'optparse'
2
+
3
+ module VagrantSnap
4
+
5
+ module Command
6
+
7
+ class Root < Vagrant.plugin("2", :command)
8
+
9
+ def initialize(argv, env)
10
+
11
+ super
12
+
13
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
14
+
15
+ @subcommands = Vagrant::Registry.new
16
+
17
+ @subcommands.register(:take) do
18
+ require_relative "take"
19
+ Take
20
+ end
21
+
22
+ @subcommands.register(:rollback) do
23
+ require_relative "rollback"
24
+ Rollback
25
+ end
26
+
27
+ @subcommands.register(:list) do
28
+ require_relative "list"
29
+ List
30
+ end
31
+
32
+
33
+ end
34
+
35
+ def execute
36
+
37
+ if @main_args.include?("-h") || @main_args.include?("--help")
38
+ return help
39
+ end
40
+
41
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
42
+ return help if !command_class || !@sub_command
43
+
44
+ # Initialize and execute the command class
45
+ command_class.new(@sub_args, @env).execute
46
+
47
+ end
48
+
49
+ def help
50
+ opts = OptionParser.new do |opts|
51
+ opts.banner = 'Usage: vagrant snap <command> [<args>]'
52
+ opts.separator ""
53
+ opts.separator "Available subcommands:"
54
+
55
+ keys = []
56
+ @subcommands.each { |key, value| keys << key.to_s }
57
+
58
+ keys.sort.each do |key|
59
+ opts.separator " #{key}"
60
+ end
61
+
62
+ opts.separator ""
63
+ opts.separator "For help on any individual command run 'vagrant snap COMMAND -h'"
64
+ end
65
+
66
+ @env.ui.info(opts.help, :prefix => false)
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,36 @@
1
+ require 'optparse'
2
+ require 'vagrant'
3
+
4
+ module VagrantSnap
5
+
6
+ module Command
7
+
8
+ class Take < Vagrant.plugin("2", :command)
9
+
10
+ def execute
11
+
12
+ options = {}
13
+
14
+ opts = OptionParser.new do |o|
15
+ o.banner = "Usage: vagrant snap take [vm-name]"
16
+ o.separator ""
17
+ end
18
+
19
+ argv = parse_options(opts)
20
+ return if !argv
21
+
22
+ with_target_vms(argv) do |vm|
23
+
24
+ vm.action(:snapshot_take)
25
+
26
+ end
27
+
28
+ 0
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,30 @@
1
+ require 'vagrant'
2
+
3
+ module VagrantSnap
4
+ class Plugin < Vagrant.plugin("2")
5
+
6
+ require_relative "command/root"
7
+ require_relative "providers/virtualbox/action"
8
+ require_relative "providers/virtualbox/driver/base"
9
+ require_relative "providers/vmware_fusion/action"
10
+ require_relative "providers/vmware_fusion/driver/base"
11
+
12
+ name "snap command"
13
+
14
+ description <<-DESC
15
+ This command provides snapshot features across multiple
16
+ Vagrant providers
17
+ DESC
18
+
19
+ command("snap") do
20
+ setup_i18n
21
+ Command::Root
22
+ end
23
+
24
+ def self.setup_i18n
25
+ I18n.load_path << File.expand_path("locales/en.yml", VagrantSnap.source_root)
26
+ I18n.reload!
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ module VagrantPlugins
2
+
3
+ module ProviderVirtualBox
4
+
5
+ module Action
6
+
7
+ class SnapshotRollback
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ end
12
+
13
+ def call(env)
14
+
15
+ env[:ui].info I18n.t("vagrant_snap.actions.vm.snapshot_rollback.rolling_back")
16
+
17
+ # Snapshot rollback involves powering off and on the VM
18
+ # so we need to find the gui state
19
+ boot_mode = env[:machine].provider_config.gui ? "gui" : "headless"
20
+
21
+ env[:machine].provider.driver.snapshot_rollback(boot_mode)
22
+
23
+ @app.call(env)
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,28 @@
1
+ module VagrantPlugins
2
+
3
+ module ProviderVirtualBox
4
+
5
+ module Action
6
+
7
+ class SnapshotTake
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ end
12
+
13
+ def call(env)
14
+
15
+ env[:ui].info I18n.t("vagrant_snap.actions.vm.snapshot_take.taking")
16
+ env[:machine].provider.driver.snapshot_take
17
+
18
+ @app.call(env)
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,46 @@
1
+ require "vagrant/action/builder"
2
+
3
+ module VagrantPlugins
4
+
5
+ module ProviderVirtualBox
6
+
7
+ module Action
8
+
9
+ autoload :SnapshotTake, File.expand_path("../action/snapshot_take.rb", __FILE__)
10
+ autoload :SnapshotRollback, File.expand_path("../action/snapshot_rollback.rb", __FILE__)
11
+
12
+ def self.action_snapshot_take
13
+ Vagrant::Action::Builder.new.tap do |b|
14
+ b.use CheckVirtualbox
15
+ b.use Call, Created do |env, b2|
16
+ if env[:result]
17
+ b2.use CheckAccessible
18
+ b2.use SnapshotTake
19
+ else
20
+ b2.use MessageNotCreated
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.action_snapshot_rollback
27
+ Vagrant::Action::Builder.new.tap do |b|
28
+ b.use CheckVirtualbox
29
+ b.use Call, Created do |env, b2|
30
+ if env[:result]
31
+ b2.use CheckAccessible
32
+ b2.use SnapshotRollback
33
+ else
34
+ b2.use MessageNotCreated
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+
@@ -0,0 +1,38 @@
1
+ module VagrantPlugins
2
+
3
+ module ProviderVirtualBox
4
+
5
+ module Driver
6
+
7
+ class Base
8
+
9
+ def snapshot_take
10
+ execute("snapshot", @uuid, "take", "vagrant-snap-#{Time.now.to_i}", "--pause")
11
+ end
12
+
13
+ def snapshot_rollback(bootmode)
14
+ halt
15
+ sleep 2 # race condition on locked VMs otherwise?
16
+ execute("snapshot", @uuid, "restore", snapshot_list.first)
17
+ start(bootmode)
18
+ end
19
+
20
+ def snapshot_list
21
+ # XXX blows up if no snapshots on the VM - how to prevent this?
22
+ info = execute("showvminfo", @uuid, "--machinereadable")
23
+ snapshots = []
24
+ info.split("\n").each do |line|
25
+ if line =~ /^SnapshotName="(.+?)"$/
26
+ snapshots << $1.to_s
27
+ end
28
+ end
29
+ snapshots
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,33 @@
1
+ module HashiCorp
2
+
3
+ module VagrantVMwarefusion
4
+
5
+ module Action
6
+
7
+ class SnapshotRollback
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ end
12
+
13
+ def call(env)
14
+
15
+ env[:ui].info I18n.t("vagrant_snap.actions.vm.snapshot_rollback.rolling_back")
16
+
17
+ # Snapshot rollback involves powering off and on the VM
18
+ # so we need to find the gui state
19
+ boot_mode = env[:machine].provider_config.gui ? "gui" : "headless"
20
+
21
+ env[:machine].provider.driver.snapshot_rollback(boot_mode)
22
+
23
+ @app.call(env)
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,28 @@
1
+ module HashiCorp
2
+
3
+ module VagrantVMwarefusion
4
+
5
+ module Action
6
+
7
+ class SnapshotTake
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ end
12
+
13
+ def call(env)
14
+
15
+ env[:ui].info I18n.t("vagrant_snap.actions.vm.snapshot_take.taking")
16
+ env[:machine].provider.driver.snapshot_take
17
+
18
+ @app.call(env)
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,44 @@
1
+ require "vagrant/action/builder"
2
+
3
+ module HashiCorp
4
+
5
+ module VagrantVMwarefusion
6
+
7
+ module Action
8
+
9
+ autoload :SnapshotTake, File.expand_path("../action/snapshot_take.rb", __FILE__)
10
+ autoload :SnapshotRollback, File.expand_path("../action/snapshot_rollback.rb", __FILE__)
11
+
12
+ def self.action_snapshot_take
13
+ Vagrant::Action::Builder.new.tap do |b|
14
+ b.use CheckVMware
15
+ b.use Call, Created do |env, b2|
16
+ if env[:result]
17
+ b2.use SnapshotTake
18
+ else
19
+ b2.use MessageNotCreated
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.action_snapshot_rollback
26
+ Vagrant::Action::Builder.new.tap do |b|
27
+ b.use CheckVMware
28
+ b.use Call, Created do |env, b2|
29
+ if env[:result]
30
+ b2.use SnapshotRollback
31
+ else
32
+ b2.use MessageNotCreated
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+
@@ -0,0 +1,34 @@
1
+ module HashiCorp
2
+
3
+ module VagrantVMwarefusion
4
+
5
+ module Driver
6
+
7
+ class Fusion
8
+
9
+ def snapshot_take
10
+ vmrun("snapshot", "#{vmx_path}", "vagrant-snap-#{Time.now.to_i}")
11
+ end
12
+
13
+ def snapshot_rollback(bootmode)
14
+ vmrun("revertToSnapshot", "#{vmx_path}", snapshot_list.first)
15
+ start
16
+ end
17
+
18
+ def snapshot_list
19
+ snapshots = []
20
+ vmrun("listSnapshots", "#{vmx_path}").stdout.split("\n").each do |line|
21
+ if line =~ /^vagrant-snap-/
22
+ snapshots << line
23
+ end
24
+ end
25
+ snapshots.sort
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,5 @@
1
+ module Vagrant
2
+ module Snap
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require "vagrant-multiprovider-snap/version"
2
+ require "vagrant-multiprovider-snap/plugin"
3
+
4
+ module VagrantSnap
5
+ def self.source_root
6
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require "vagrant-multiprovider-snap/version"
2
+ require "vagrant-multiprovider-snap/plugin"
3
+
4
+ module VagrantSnap
5
+ def self.source_root
6
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
7
+ end
8
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,19 @@
1
+ en:
2
+ vagrant_snap:
3
+ commands:
4
+ list:
5
+ output: |-
6
+ Current available snapshots by VM:
7
+
8
+ %{snapshots}
9
+
10
+ actions:
11
+ vm:
12
+ snapshot_take:
13
+ taking: |-
14
+ Taking snapshot.
15
+ snapshot_rollback:
16
+ rolling_back: |-
17
+ Rolling back to previous snapshot
18
+
19
+
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "vagrant-multiprovider-snap/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "vagrant-zz-multiprovider-snap"
7
+ s.version = Vagrant::Snap::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jon Topper"]
10
+ s.email = ["jon@scalefactory.com"]
11
+ s.homepage = "http://github.com/scalefactory/vagrant-multiprovider-snap"
12
+
13
+ s.summary = %q{Multi-provider snapshots for Vagrant}
14
+ s.description = %q{Multi-provider snapshots for Vagrant}
15
+
16
+ s.rubyforge_project = "vagrant-multiprovider-snap"
17
+
18
+ files = `git ls-files`.split("\n")
19
+ ignore = %w{rgloader/* Gemfile Rakefile Vagrantfile .gitignore}
20
+
21
+ files.delete_if do |f|
22
+ ignore.any? do |i|
23
+ File.fnmatch(i, f, File::FNM_PATHNAME) ||
24
+ File.fnmatch(i, File.basename(f), File::FNM_PATHNAME)
25
+ end
26
+ end
27
+
28
+ s.files = files
29
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
30
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
31
+ s.require_paths = ["lib"]
32
+
33
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-zz-multiprovider-snap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jon Topper
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-12 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Multi-provider snapshots for Vagrant
15
+ email:
16
+ - jon@scalefactory.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - README.md
22
+ - lib/vagrant-multiprovider-snap.rb
23
+ - lib/vagrant-multiprovider-snap/command/list.rb
24
+ - lib/vagrant-multiprovider-snap/command/rollback.rb
25
+ - lib/vagrant-multiprovider-snap/command/root.rb
26
+ - lib/vagrant-multiprovider-snap/command/take.rb
27
+ - lib/vagrant-multiprovider-snap/plugin.rb
28
+ - lib/vagrant-multiprovider-snap/providers/virtualbox/action.rb
29
+ - lib/vagrant-multiprovider-snap/providers/virtualbox/action/snapshot_rollback.rb
30
+ - lib/vagrant-multiprovider-snap/providers/virtualbox/action/snapshot_take.rb
31
+ - lib/vagrant-multiprovider-snap/providers/virtualbox/driver/base.rb
32
+ - lib/vagrant-multiprovider-snap/providers/vmware_fusion/action.rb
33
+ - lib/vagrant-multiprovider-snap/providers/vmware_fusion/action/snapshot_rollback.rb
34
+ - lib/vagrant-multiprovider-snap/providers/vmware_fusion/action/snapshot_take.rb
35
+ - lib/vagrant-multiprovider-snap/providers/vmware_fusion/driver/base.rb
36
+ - lib/vagrant-multiprovider-snap/version.rb
37
+ - lib/vagrant-zz-multiprovider-snap.rb
38
+ - locales/en.yml
39
+ - vagrant-multiprovider-snap.gemspec
40
+ homepage: http://github.com/scalefactory/vagrant-multiprovider-snap
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project: vagrant-multiprovider-snap
60
+ rubygems_version: 1.8.11
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Multi-provider snapshots for Vagrant
64
+ test_files: []