├── .gitignore ├── CHANGELOG.md ├── DEVNOTES.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── Vagrantfile ├── lib ├── vagrant-vbox-snapshot.rb └── vagrant-vbox-snapshot │ ├── commands │ ├── back.rb │ ├── check_runnable.rb │ ├── delete.rb │ ├── go.rb │ ├── list.rb │ ├── multi_vm_args.rb │ ├── root.rb │ └── take.rb │ ├── plugin.rb │ └── version.rb └── vagrant-vbox-snapshot.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | coverage 6 | InstalledFiles 7 | lib/bundler/man 8 | pkg 9 | rdoc 10 | spec/reports 11 | test/tmp 12 | test/version_tmp 13 | tmp 14 | 15 | # YARD artifacts 16 | .yardoc 17 | _yardoc 18 | doc/ 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.10](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.9...v0.0.10) (November 13, 2015) 2 | 3 | IMPROVEMENTS: 4 | 5 | - vagrant snapshot back and go no longer fails if the VM is in "aborted" state [#36](https://github.com/dergachev/vagrant-vbox-snapshot/pull/36) 6 | 7 | ## [0.0.9](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.8...v0.0.9) (July 3, 2015) 8 | 9 | IMPROVEMENTS: 10 | 11 | - vagrant snapshot back and go no longer fails if the VM is in "saved" state [#33](https://github.com/dergachev/vagrant-vbox-snapshot/pull/33) 12 | 13 | ## [0.0.8](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.7...v0.0.8) (October 10, 2014) 14 | 15 | IMPROVEMENTS: 16 | 17 | - make 'vagrant' dev dependency in Gemfile [#29](https://github.com/dergachev/vagrant-vbox-snapshot/issues/29) 18 | 19 | ## [0.0.7](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.6...v0.0.7) (October 7, 2014) 20 | 21 | IMPROVEMENTS: 22 | 23 | - don't crash if vm is poweroff [#28](https://github.com/dergachev/vagrant-vbox-snapshot/issues/28) 24 | 25 | ## [0.0.6](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.5...v0.0.6) (October 6, 2014) 26 | 27 | IMPROVEMENTS: 28 | 29 | - suppress 'snapshot list' error when no snapshots [#17](https://github.com/dergachev/vagrant-vbox-snapshot/issues/17) 30 | 31 | ## [0.0.5](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.4...v0.0.5) (June 7, 2014) 32 | 33 | IMPROVEMENTS: 34 | 35 | - Add command synopsys [#23](https://github.com/dergachev/vagrant-vbox-snapshot/issues/23) 36 | 37 | ## [0.0.4](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.3...v0.0.4) (Sep 23, 2013) 38 | 39 | BACKWARDS INCOMPATIBILITIES: 40 | 41 | - none 42 | 43 | FEATURES: 44 | 45 | - Add Windows compatibility [#12](https://github.com/dergachev/vagrant-vbox-snapshot/issues/12) 46 | 47 | IMPROVEMENTS: 48 | 49 | - Clean up `vagrant snapshot go` output when target is already in poweroff state. [#14](https://github.com/dergachev/vagrant-vbox-snapshot/pull/14) 50 | 51 | ## [0.0.3](https://github.com/dergachev/vagrant-vbox-snapshot/compare/v0.0.2...v0.0.3) (Sep 3, 2013) 52 | 53 | BACKWARDS INCOMPATIBILITIES: 54 | 55 | - none 56 | 57 | FEATURES: 58 | 59 | - Add multi-vm support [#6](https://github.com/dergachev/vagrant-vbox-snapshot/pull/6) 60 | 61 | IMPROVEMENTS: 62 | 63 | - Run `vagrant reload` when restoring snapshots with changed config [#2](https://github.com/dergachev/vagrant-vbox-snapshot/issues/2) 64 | -------------------------------------------------------------------------------- /DEVNOTES.md: -------------------------------------------------------------------------------- 1 | # Developer notes for vagrant-vbox-snapshot 2 | 3 | ## Forking and hacking on vagrant-vbox-snapshot 4 | 5 | ``` 6 | # fork vagrant-vbox-snapshot on github.com, and clone locally 7 | cd ~/code # or wherever you like to put coding projects 8 | git clone git@github.com/USERNAME/vagrant-vbox-snapshot.git 9 | cd vagrant-vbox-snapshot 10 | 11 | # create a new branch for your work 12 | git checkout -b FEATURE_NAME 13 | 14 | bundle install # not 100% sure this is necessary 15 | # hack away... 16 | # then test, possibly modifying Vagrantfile to suit scenario 17 | vagrant up 18 | vagrant snapshot take TEST1 # and so on... 19 | 20 | # then commit, push, and create pull request 21 | ``` 22 | 23 | ## Reviewing a pull request 24 | 25 | ``` 26 | git clone https://github.com/dergachev/vagrant-vbox-snapshot.git 27 | cd vagrant-vbox-snapshot 28 | 29 | # installs vagrant gem for local development 30 | NOKOGIRI_USE_SYSTEM_LIBRARIES=1 bundle install 31 | 32 | # consider branching if you aren't sure about merging it (not the case here, of course!) 33 | # git checkout -b dubious-pull-request 34 | git pull https://github.com/fgrehm/vagrant-vbox-snapshot multi-vm-environments-support 35 | 36 | # test, fix stuff, etc (inside the locally installed bundle) 37 | bundle exec vagrant up 38 | bundle exec vagrant snapshot go 39 | 40 | # push (merge into master if necessary) 41 | git push -u origin master 42 | ``` 43 | 44 | ## Pushing out a new release of the gem 45 | 46 | Do a local build: 47 | 48 | ``` 49 | vim lib/vagrant-vbox-snapshot/version.rb +/VERSION # increment version counter, eg to 0.0.3 50 | gem build vagrant-vbox-snapshot.gemspec # creates vagrant-vbox-snapshot-0.0.3.gem 51 | ``` 52 | 53 | Test the local build: 54 | 55 | ``` 56 | # test the gem locally, in a random vagrant project 57 | cd ~/code/screengif 58 | vagrant plugin uninstall vagrant-vbox-snapshot 59 | vagrant plugin install ~/code/vagrant-vbox-snapshot/vagrant-vbox-snapshot-VERSION.gem # replace VERSION with 0.0.3 60 | vagrant plugin list | grep snapshot # ensure that correct version is installed 61 | vagrant snapshot list -h # quick sanity check 62 | vagrant plugin uninstall vagrant-vbox-snapshot # cleanup 63 | ``` 64 | 65 | Now commit and tag: 66 | 67 | 68 | ``` 69 | cd ~/code/vagrant-vbox-snapshot 70 | 71 | vim CHANGELOG.txt # update CHANGELOG 72 | # git commit everything 73 | 74 | gem push vagrant-vbox-snapshot-0.0.3.gem 75 | git tag vN.N.N # eg v0.0.3 76 | git push --tags 77 | ``` 78 | 79 | Test installing from rubygems 80 | 81 | ``` 82 | cd ~/code/screengif 83 | vagrant plugin install vagrant-vbox-snapshot 84 | ``` 85 | 86 | 87 | ## Updating to vagrant 1.1 plugin API 88 | 89 | Resources: 90 | 91 | * http://docs.vagrantup.com/v2/plugins/development-basics.html 92 | * http://railscasts.com/episodes/245-new-gem-with-bundler?view=asciicast (Gem tutorial) 93 | 94 | Example code: 95 | 96 | * https://gist.github.com/dergachev/5367385#vagrant-snapshot.rb 97 | * https://github.com/mitchellh/vagrant/issues/143#add-vagrant-snapshot-option 98 | * https://github.com/fgrehm/vagrant-notify 99 | * https://github.com/RiotGames/berkshelf-vagrant 100 | * https://github.com/mitchellh/vagrant-aws/blob/master/lib/vagrant-aws/plugin.rb 101 | * sahara 1.1 update commit: https://github.com/ryuzee/sahara/commit/b80a621a9200bb4935c782bd4e538886c42b8643 102 | * vagrant-snap: https://github.com/t9md/vagrant-snap/blob/master/lib/vagrant_snap.rb 103 | * https://github.com/dotless-de/vagrant-plugins-env/blob/master/.gitmodules 104 | 105 | Vagrant source code: 106 | 107 | * https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/registry.rb 108 | * https://github.com/mitchellh/vagrant/tree/master/plugins/provisioners/shell 109 | * https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/plugin/v2/provisioner.rb 110 | * https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/plugin/v2/command.rb 111 | 112 | ## other ideas related to snapshots 113 | 114 | * http://code.chrisroberts.org/blog/2012/05/09/cooking-up-partial-run-lists-with-chef/ 115 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in vagrant-snap.gemspec 4 | # gemspec 5 | 6 | group :development do 7 | gem "vagrant", git: "https://github.com/mitchellh/vagrant.git" 8 | end 9 | 10 | group :plugins do 11 | gem "vagrant-vbox-snapshot", path: "." 12 | end 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Alex Dergachev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vagrant-vbox-snapshot 2 | ================================== 3 | Vagrant plugin that exposes the `VBoxManage snapshot` command. 4 | 5 | As of Q4 2015, the [vagrant snapshot](https://www.vagrantup.com/docs/cli/snapshot.html) command is provided by core Vagrant. Consider using it in preference to this plugin. 6 | 7 | ## Install 8 | 9 | Ensure you have Vagrant 1.1+ installed, then run: 10 | 11 | vagrant plugin install vagrant-vbox-snapshot 12 | 13 | ## Usage 14 | 15 | The following commands are added by this plugin: 16 | 17 | vagrant snapshot take [vm-name] # take snapshot, labeled by NAME 18 | vagrant snapshot list [vm-name] # list snapshots 19 | vagrant snapshot back [vm-name] # restore last taken snapshot 20 | vagrant snapshot delete [vm-name] # delete specified snapshot 21 | vagrant snapshot go [vm-name] # restore specified snapshot 22 | 23 | ## Caveats 24 | 25 | * Not compatible with Vagrant <1.1. If you need this, try [another solution](#other-solutions). 26 | 27 | ## Other solutions 28 | 29 | This plugin is primarily a port of vagrant-snap to Vagrant 1.1. 30 | 31 | * [vagrant-snap](https://github.com/t9md/vagrant-snap) 32 | - fork with Vagrant 1.0.4-1.0.7 compatibility: https://gist.github.com/tombh/5142237 [source](https://github.com/mitchellh/vagrant/issues/143#issuecomment-14781762) 33 | * [sahara](https://github.com/jedi4ever/sahara) 34 | - supports 1.1 35 | 36 | ## Development 37 | 38 | To develop on this plugin, do the following: 39 | 40 | ``` 41 | # get the repo, and then make a feature branch (REPLACE WITH YOUR FORK) 42 | git clone https://github.com/dergachev/vagrant-vbox-snapshot.git 43 | cd vagrant-vbox-snapshot 44 | git checkout -b MY-NEW-FEATURE 45 | 46 | # installs the vagrant gem, which is a dev dependency 47 | bundle install 48 | 49 | # hack on the plugin 50 | vim lib/vagrant-vbox-snapshot.rb # or any other file 51 | 52 | # test out your changes, in the context provided by the development vagrant gem, and the local Vagrantfile. 53 | bundle exec vagrant snapshot ... 54 | 55 | # commit, push, and do a pull-request 56 | ``` 57 | 58 | See [DEVNOTES.md](https://github.com/dergachev/vagrant-vbox-snapshot/blob/master/DEVNOTES.md) 59 | for the notes I compiled while developing this plugin. 60 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # -*- mode: ruby -*- 3 | # vi: set ft=ruby : 4 | 5 | require_relative 'lib/vagrant-vbox-snapshot.rb' 6 | 7 | Vagrant.configure("2") do |config| 8 | 9 | TEST_MULTI_VM = false 10 | TEST_SHARED_FOLDERS = false 11 | 12 | if TEST_MULTI_VM 13 | config.vm.define :web do |web| 14 | web.vm.box = "precise64" 15 | end 16 | config.vm.define :db do |web| 17 | web.vm.box = "precise64" 18 | end 19 | else 20 | config.vm.box = "precise64" 21 | config.vm.box_url = "http://files.vagrantup.com/precise64.box" 22 | end 23 | 24 | if TEST_SHARED_FOLDERS 25 | config.vm.synced_folder "/tmp", "/tmp/host-tmp" 26 | config.vm.synced_folder "/tmp", "/tmp/host-tmp2" 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot.rb: -------------------------------------------------------------------------------- 1 | require_relative 'vagrant-vbox-snapshot/version.rb' 2 | require_relative 'vagrant-vbox-snapshot/plugin.rb' 3 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/back.rb: -------------------------------------------------------------------------------- 1 | require_relative 'multi_vm_args' 2 | require_relative 'check_runnable' 3 | 4 | module VagrantPlugins 5 | module VBoxSnapshot 6 | module Command 7 | class Back < Vagrant.plugin(2, :command) 8 | include CheckRunnable 9 | 10 | def execute 11 | options = {} 12 | 13 | opts = OptionParser.new do |opts| 14 | opts.banner = "Back to current snapshot" 15 | opts.separator "" 16 | opts.separator "Usage: vagrant snapshot back [vm-name]" 17 | end 18 | # Parse the options 19 | argv = parse_options(opts) 20 | return if !argv 21 | 22 | with_target_vms(argv, single_target: true) do |machine| 23 | check_runnable_on(machine) 24 | 25 | if machine.state.id != :poweroff and machine.state.id != :saved and machine.state.id != :aborted 26 | machine.provider.driver.execute("controlvm", machine.id, "poweroff") 27 | end 28 | 29 | machine.provider.driver.execute("snapshot", machine.id, "restorecurrent") do |type, data| 30 | machine.env.ui.info(data, :color => type == :stderr ? :red : :white, :new_line => false) 31 | end 32 | 33 | if options[:reload] 34 | @env.ui.info("Reloading VM, since --reload passed") 35 | machine.action(:reload, :provision_enabled => false) 36 | else 37 | @env.ui.info("Starting restored VM") 38 | machine.action(:up, :provision_enabled => false) 39 | end 40 | end 41 | end 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/check_runnable.rb: -------------------------------------------------------------------------------- 1 | # Adapted from https://github.com/dotless-de/vagrant-vbguest/ 2 | 3 | require Vagrant.source_root.join("plugins/commands/up/start_mixins") 4 | 5 | module VagrantPlugins 6 | module VBoxSnapshot 7 | module Command 8 | 9 | module CheckRunnable 10 | 11 | include VagrantPlugins::CommandUp::StartMixins 12 | 13 | class NoVirtualBoxMachineError < Vagrant::Errors::VagrantError 14 | error_message "The VBGuest plugin must be used with VirtualBox Machines only." 15 | end 16 | 17 | def check_runnable_on(vm) 18 | raise NoVirtualBoxMachineError if vm.provider.class != VagrantPlugins::ProviderVirtualBox::Provider 19 | raise Vagrant::Errors::VMNotCreatedError if vm.state.id == :not_created 20 | end 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/delete.rb: -------------------------------------------------------------------------------- 1 | # this command is very slow 2 | # consider removing it; or replacing with this idea: http://superuser.com/questions/590968/quickest-way-to-merge-snapshots-in-virtualbox 3 | 4 | require_relative 'multi_vm_args' 5 | require_relative 'check_runnable' 6 | 7 | module VagrantPlugins 8 | module VBoxSnapshot 9 | module Command 10 | class Delete < Vagrant.plugin(2, :command) 11 | include MultiVmArgs 12 | include CheckRunnable 13 | 14 | def execute 15 | options = {} 16 | 17 | opts = OptionParser.new do |opts| 18 | opts.banner = "Delete snapshot (warning: this is a very slow operation)" 19 | opts.separator "" 20 | opts.separator "Usage: vagrant snapshot delete [vm-name] " 21 | end 22 | # Parse the options 23 | argv = parse_options(opts) 24 | return if !argv 25 | 26 | vm_name, snapshot_name = parse_vm_and_snapshot_options(argv, opts) 27 | return if !snapshot_name 28 | 29 | with_target_vms(vm_name, single_target: true) do |machine| 30 | check_runnable_on(machine) 31 | machine.provider.driver.execute("snapshot", machine.id, "delete", snapshot_name) do |type, data| 32 | machine.env.ui.info(data, :color => type == :stderr ? :red : :white) 33 | end 34 | end 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/go.rb: -------------------------------------------------------------------------------- 1 | require_relative 'multi_vm_args' 2 | require_relative 'check_runnable' 3 | 4 | module VagrantPlugins 5 | module VBoxSnapshot 6 | module Command 7 | class Go < Vagrant.plugin(2, :command) 8 | include MultiVmArgs 9 | include CheckRunnable 10 | 11 | def get_shared_folders(machine) 12 | shared_folders = [] 13 | info = machine.provider.driver.execute("showvminfo", machine.id, "--machinereadable") 14 | info.split("\n").each do |line| 15 | if line =~ /^SharedFolderNameMachineMapping\d+="(.+?)"$/ 16 | shared_folders << $1.to_s 17 | end 18 | end 19 | return shared_folders 20 | end 21 | 22 | def before_restore(machine) 23 | @shared_folders_before = get_shared_folders(machine) 24 | end 25 | 26 | def after_restore(machine) 27 | @shared_folders_after = get_shared_folders(machine) 28 | if @shared_folders_before != @shared_folders_after 29 | @env.ui.warn("Synced folders have changed after restoring snapshot. Consider running 'vagrant reload'.") 30 | @env.ui.warn(" Before restore: #{@shared_folders_before}") 31 | @env.ui.warn(" After restore: #{@shared_folders_after}") 32 | end 33 | end 34 | 35 | def execute 36 | options = {} 37 | options[:reload] = false 38 | 39 | opts = OptionParser.new do |opts| 40 | opts.banner = "Go to specified snapshot" 41 | opts.separator "" 42 | opts.separator "Usage: vagrant snapshot go [vm-name] " 43 | 44 | opts.on("-r", "--reload", "Runs 'vagrant reload --no-provision' after restoring snapshot to ensure Vagrantfile config is applied.") do |reload| 45 | options[:reload] = reload 46 | end 47 | 48 | end 49 | # Parse the options 50 | argv = parse_options(opts) 51 | return if !argv 52 | 53 | vm_name, snapshot_name = parse_vm_and_snapshot_options(argv, opts) 54 | return if !snapshot_name 55 | 56 | with_target_vms(vm_name, single_target: true) do |machine| 57 | check_runnable_on(machine) 58 | vm_id = machine.id 59 | 60 | before_restore(machine) 61 | 62 | if machine.state.id != :poweroff and machine.state.id != :saved and machine.state.id != :aborted 63 | @env.ui.info("Powering off machine #{vm_id}") 64 | machine.provider.driver.execute("controlvm", machine.id, "poweroff") 65 | end 66 | 67 | machine.provider.driver.execute("snapshot", machine.id, "restore", snapshot_name) do |type, data| 68 | machine.env.ui.info(data, :color => type == :stderr ? :red : :white, :new_line => false) 69 | end 70 | 71 | if options[:reload] 72 | @env.ui.info("Reloading VM, since --reload passed") 73 | machine.action(:reload, :provision_enabled => false) 74 | else 75 | @env.ui.info("Starting restored VM") 76 | machine.action(:up, :provision_enabled => false) 77 | end 78 | 79 | after_restore(machine) 80 | end 81 | end 82 | end 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/list.rb: -------------------------------------------------------------------------------- 1 | require_relative 'check_runnable' 2 | 3 | module VagrantPlugins 4 | module VBoxSnapshot 5 | module Command 6 | class List < Vagrant.plugin(2, :command) 7 | include CheckRunnable 8 | def execute 9 | options = {} 10 | 11 | opts = OptionParser.new do |opts| 12 | opts.banner = "List snapshots" 13 | opts.separator "" 14 | opts.separator "Usage: vagrant snapshot list" 15 | end 16 | # Parse the options 17 | argv = parse_options(opts) 18 | return if !argv 19 | 20 | with_target_vms(argv, single_target: true) do |machine| 21 | check_runnable_on(machine) 22 | puts "Listing snapshots for '#{machine.name}':" 23 | 24 | begin 25 | res = machine.provider.driver.execute("snapshot", machine.id, "list", "--details") do |type, data| 26 | @suppress_error = TRUE if data == "This machine does not have any snapshots\n" 27 | machine.env.ui.info(data, :color => :green) if (type == :stdout) 28 | end 29 | rescue Vagrant::Errors::VBoxManageError => e 30 | raise e unless @suppress_error 31 | end 32 | end 33 | end 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/multi_vm_args.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins 2 | module VBoxSnapshot 3 | module Command 4 | module MultiVmArgs 5 | def parse_vm_and_snapshot_options(argv, opts) 6 | unless [1, 2].include?(argv.size) 7 | @env.ui.info(opts.help, :prefix => false) 8 | return 9 | end 10 | 11 | if argv.size == 1 12 | [nil, argv[0]] 13 | else 14 | [argv[0], argv[1]] 15 | end 16 | end 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/root.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins 2 | module VBoxSnapshot 3 | module Command 4 | class Root < Vagrant.plugin(2, :command) 5 | def self.synopsis 6 | "manages snapshots of the machine: taking, restoring, deleting, etc." 7 | end 8 | 9 | def initialize(argv, env) 10 | super 11 | 12 | @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv) 13 | 14 | @subcommands = Vagrant::Registry.new 15 | @subcommands.register(:take) do 16 | require_relative('take') 17 | Take 18 | end 19 | @subcommands.register(:list) do 20 | require_relative('list') 21 | List 22 | end 23 | @subcommands.register(:go) do 24 | require_relative('go') 25 | Go 26 | end 27 | @subcommands.register(:back) do 28 | require_relative('back') 29 | Back 30 | end 31 | @subcommands.register(:delete) do 32 | require_relative('delete') 33 | Delete 34 | end 35 | end 36 | 37 | def execute 38 | if @main_args.include?("-h") || @main_args.include?("--help") 39 | # Print the help for all the box commands. 40 | return help 41 | end 42 | 43 | # If we reached this far then we must have a subcommand. If not, 44 | # then we also just print the help and exit. 45 | command_class = @subcommands.get(@sub_command.to_sym) if @sub_command 46 | return help if !command_class || !@sub_command 47 | @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}") 48 | 49 | # Initialize and execute the command class 50 | command_class.new(@sub_args, @env).execute 51 | end 52 | 53 | # Prints the help out for this command 54 | def help 55 | opts = OptionParser.new do |opts| 56 | opts.banner = "Usage: vagrant snapshot []" 57 | opts.separator "" 58 | opts.separator "Available subcommands:" 59 | 60 | # Add the available subcommands as separators in order to print them 61 | # out as well. 62 | keys = [] 63 | @subcommands.each { |key, value| keys << key.to_s } 64 | 65 | keys.sort.each do |key| 66 | opts.separator " #{key}" 67 | end 68 | 69 | opts.separator "" 70 | opts.separator "For help on any individual command run `vagrant snapshot -h`" 71 | end 72 | 73 | @env.ui.info(opts.help, :prefix => false) 74 | end 75 | 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/commands/take.rb: -------------------------------------------------------------------------------- 1 | require_relative 'multi_vm_args' 2 | require_relative 'check_runnable' 3 | 4 | module VagrantPlugins 5 | module VBoxSnapshot 6 | module Command 7 | class Take < Vagrant.plugin(2, :command) 8 | include MultiVmArgs 9 | include CheckRunnable 10 | 11 | def execute 12 | options = {} 13 | 14 | opts = OptionParser.new do |opts| 15 | opts.banner = "Take snapshot" 16 | opts.separator "" 17 | opts.separator "Usage: vagrant snapshot take [vm-name] " 18 | end 19 | # Parse the options 20 | argv = parse_options(opts) 21 | return if !argv 22 | 23 | vm_name, snapshot_name = parse_vm_and_snapshot_options(argv, opts) 24 | return if !snapshot_name 25 | 26 | with_target_vms(vm_name, single_target: true) do |machine| 27 | check_runnable_on(machine) 28 | machine.env.ui.info("Taking snapshot #{snapshot_name}") 29 | machine.provider.driver.execute("snapshot", machine.id, "take", snapshot_name, "--pause") do |type, data| 30 | machine.env.ui.info(data, :color => type == :stderr ? :red : :white, :new_line => false) 31 | end 32 | end 33 | end 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/plugin.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require "vagrant" 3 | rescue LoadError 4 | raise "The Vagrant VBox Snapshot plugin must be run within Vagrant." 5 | end 6 | 7 | module VagrantPlugins 8 | module VBoxSnapshot 9 | class Plugin < Vagrant.plugin("2") 10 | name "Vagrant VBox Snapshot" 11 | description "Wrapper on the `VBoxManage snapshot` command." 12 | 13 | command "snapshot" do 14 | require_relative 'commands/root.rb' 15 | Command::Root 16 | end 17 | 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/vagrant-vbox-snapshot/version.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins 2 | module VBoxSnapshot 3 | VERSION = "0.0.10" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /vagrant-vbox-snapshot.gemspec: -------------------------------------------------------------------------------- 1 | $:.unshift File.expand_path('../lib', __FILE__) 2 | require 'vagrant-vbox-snapshot/version' 3 | 4 | Gem::Specification.new do |spec| 5 | spec.name = "vagrant-vbox-snapshot" 6 | spec.version = VagrantPlugins::VBoxSnapshot::VERSION 7 | spec.authors = "Alex Dergachev" 8 | spec.email = "alex@evolvingweb.ca" 9 | spec.summary = 'Vagrant plugin that exposes the `VBoxManage snapshot` command.' 10 | spec.description = 'Vagrant plugin that exposes the `VBoxManage snapshot` command.' 11 | spec.homepage = 'https://github.com/dergachev/vagrant-vbox-snapshot' 12 | spec.license = "MIT" 13 | 14 | spec.files = `git ls-files`.split($/) 15 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 16 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 17 | spec.require_path = 'lib' 18 | 19 | spec.add_development_dependency "bundler" 20 | spec.add_development_dependency "rake" 21 | end 22 | --------------------------------------------------------------------------------