Skip to content

Instantly share code, notes, and snippets.

@dergachev
Forked from tombh/vagrant-snapshot.rb
Created April 11, 2013 21:35

Revisions

  1. @tombh tombh revised this gist Mar 12, 2013. 1 changed file with 98 additions and 69 deletions.
    167 changes: 98 additions & 69 deletions vagrant-snapshot.rb
    Original file line number Diff line number Diff line change
    @@ -1,106 +1,135 @@
    ## place this file to same directory of `Vagrantfile' then simply require "snap.rb" in Vagrantfile
    # Place this file in the same directory as `Vagrantfile'
    # then simply require "vagrant-snapshot.rb" at the top of Vagrantfile.

    require 'optparse'

    Vagrant.commands.register(:snap) { Snap::Commands }

    # Provide rake-like desc() 'inflected' documentation
    # See http://stackoverflow.com/questions/2948328/access-attributes-methods-comments-programmatically-in-ruby
    class Module
    private

    old_method_added = instance_method :method_added
    define_method :method_added do |meth|
    (@__doc__ ||= {})[meth] = @__last_doc__ if @__last_doc__
    @__last_doc__ = nil
    old_method_added.bind(self).(meth)
    end

    def doc(usage, description)
    @__last_doc__ = [usage, description]
    end

    end

    module Kernel
    private

    def get_doc(klass, meth)
    klass.instance_variable_get(:@__doc__)[meth]
    end
    end

    # Snap commands
    module Snap
    module VBox
    class SnapShot
    require "forwardable"
    extend Forwardable
    def_delegators :@snap, :name, :uuid, :time_stamp
    @@snaps = []
    class << self
    def is_endnode?() @@current.uuid == @@snaps.last.uuid end

    def snaps() @@snaps end

    def parse_tree(vmname)
    vm = VirtualBox::VM.find( vmname )
    @@current = vm.current_snapshot
    return unless @@current
    new(vm.root_snapshot).walk
    end
    end
    class Commands < ::Vagrant::Command::Base

    def initialize(snap)
    @snap = snap
    self.class.snaps << self
    end
    def current?
    snap.uuid == @@current.uuid
    end
    def register
    end
    attr_reader :snap
    def initialize(argv,env)
    super
    @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
    end

    def have_child?
    ! @snap.children.empty?
    def execute
    if @main_args.include?("-h") || @main_args.include?("--help")
    # Print the help for all the box commands.
    return help
    end

    def first_child
    snap.children.first
    # If we reached this far then we must have a subcommand. If not,
    # then we also just print the help and exit.
    command = sub_commands[@sub_command.to_sym] if @sub_command
    return help if !command || !@sub_command

    # If the command has wrong args.
    # Word count is used to determine if args required.
    if command[0].split.size - 1 != @sub_args.size
    return help command[0], command[1]
    end

    def walk
    if have_child?
    s = self.class.new first_child
    s.walk
    # Finally run the command
    @logger.debug("Invoking command : #{command} #{@sub_args.inspect}")
    self.send(@sub_command, *@sub_args)
    end

    def vmname
    @vagrant_env ||= Vagrant::Environment.new
    @instance_name ||= "#{@vagrant_env.vms[:default].uuid}"
    @instance_name
    end

    def sub_commands
    subs = {}
    methods.each do |m|
    doc_data = get_doc(Snap::Commands, m.to_sym)
    if doc_data
    subs[m] = doc_data
    end
    end
    subs
    end
    end

    class Command < Vagrant::Command::GroupBase
    register "snap","Manages a snap"
    doc "help", "Show this help"
    def help command = nil, description = nil
    options = OptionParser.new do |opts|
    if command && description
    opts.banner = description
    opts.separator ""
    opts.separator "Usage: vagrant snap #{command}"
    else
    opts.banner = "Usage: vagrant snap <command> [<args>]"
    opts.separator ""
    opts.separator "Available subcommands:"

    no_tasks {
    def vmname
    @vagrant_env ||= Vagrant::Environment.new
    @instance_name ||= "#{@vagrant_env.vms[:default].vm.name}"
    @instance_name
    # Add the available subcommands as separators in order to print them
    # out as well.
    sub_commands.each do |sub_command, doc_data|
    opts.separator " #{doc_data[0].ljust(18)} #{doc_data[1]}"
    end
    end
    end
    }

    desc "list", "list snapshot"
    @env.ui.info(options.help, :prefix => false)
    end

    doc "list", "List snapshots"
    def list
    format = " %s %-20s %s"
    VBox::SnapShot.parse_tree( vmname )
    result = VBox::SnapShot.snaps.map do |s|
    cur_mark = s.current? ? "*" : " "
    format % [ cur_mark, s.time_stamp.strftime("%Y%m%d-%H:%M:%S"), s.name ]
    end
    puts result
    system "VBoxManage snapshot #{vmname} list --details"
    end

    desc "go [SNAPNAME]", "go to specified snapshot"
    doc "go [SNAPNAME]", "Go to specified snapshot"
    def go(snapshot_name)
    system "VBoxManage controlvm #{vmname} poweroff"
    system "VBoxManage snapshot #{vmname} restore #{snapshot_name}"
    system "VBoxManage startvm #{vmname} --type headless"
    end

    desc "back", "back to current snapshot"
    doc "back", "Back to current snapshot"
    def back
    system "VBoxManage controlvm #{vmname} poweroff"
    system "VBoxManage snapshot #{vmname} restorecurrent"
    system "VBoxManage startvm #{vmname} --type headless"
    end

    desc "take", "take snapshot"
    def take
    VBox::SnapShot.parse_tree( vmname )
    last = VBox::SnapShot.snaps.last
    new_name = last ? last.name.succ : vmname + "-01"
    # new_name = last.name.succ
    if not last or VBox::SnapShot.is_endnode?
    system "VBoxManage snapshot #{vmname} take #{new_name} --pause"
    else
    puts "Can not create"
    end
    doc "take [SNAPNAME]", "Take snapshot"
    def take(snapshot_name)
    system "VBoxManage snapshot #{vmname} take #{snapshot_name} --pause"
    end

    desc "delete", "delete snapshot"
    doc "delete [SNAPNAME]", "Delete snapshot"
    def delete(snapshot_name)
    system "VBoxManage snapshot #{vmname} delete #{snapshot_name}"
    end
    end
    end

    end
  2. @t9md t9md revised this gist Jun 4, 2011. 1 changed file with 20 additions and 19 deletions.
    39 changes: 20 additions & 19 deletions vagrant-snapshot.rb
    Original file line number Diff line number Diff line change
    @@ -48,8 +48,8 @@ def walk
    end
    end

    class Command < Vagrant::Command::GroupBase
    register "snap","Manages a snap"
    class Command < Vagrant::Command::GroupBase
    register "snap","Manages a snap"

    no_tasks {
    def vmname
    @@ -59,33 +59,33 @@ def vmname
    end
    }

    desc "list", "list snapshot"
    def list
    desc "list", "list snapshot"
    def list
    format = " %s %-20s %s"
    VBox::SnapShot.parse_tree( vmname )
    result = VBox::SnapShot.snaps.map do |s|
    cur_mark = s.current? ? "*" : " "
    format % [ cur_mark, s.time_stamp.strftime("%Y%m%d-%H:%M:%S"), s.name ]
    end
    puts result
    end
    end

    desc "go [SNAPNAME]", "go to specified snapshot"
    def go(snapshot_name)
    desc "go [SNAPNAME]", "go to specified snapshot"
    def go(snapshot_name)
    system "VBoxManage controlvm #{vmname} poweroff"
    system "VBoxManage snapshot #{vmname} restore #{snapshot_name}"
    system "VBoxManage startvm #{vmname} --type headless"
    end
    end

    desc "back", "back to current snapshot"
    def back
    desc "back", "back to current snapshot"
    def back
    system "VBoxManage controlvm #{vmname} poweroff"
    system "VBoxManage snapshot #{vmname} restorecurrent"
    system "VBoxManage startvm #{vmname} --type headless"
    end
    end

    desc "take", "take snapshot"
    def take
    desc "take", "take snapshot"
    def take
    VBox::SnapShot.parse_tree( vmname )
    last = VBox::SnapShot.snaps.last
    new_name = last ? last.name.succ : vmname + "-01"
    @@ -95,11 +95,12 @@ def take
    else
    puts "Can not create"
    end
    end
    end

    desc "delete", "delete snapshot"
    def delete(snapshot_name)
    desc "delete", "delete snapshot"
    def delete(snapshot_name)
    system "VBoxManage snapshot #{vmname} delete #{snapshot_name}"
    end
    end
    end
    end
    end
    end

  3. @t9md t9md created this gist Jun 4, 2011.
    105 changes: 105 additions & 0 deletions vagrant-snapshot.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,105 @@
    ## place this file to same directory of `Vagrantfile' then simply require "snap.rb" in Vagrantfile

    module Snap
    module VBox
    class SnapShot
    require "forwardable"
    extend Forwardable
    def_delegators :@snap, :name, :uuid, :time_stamp
    @@snaps = []
    class << self
    def is_endnode?() @@current.uuid == @@snaps.last.uuid end

    def snaps() @@snaps end

    def parse_tree(vmname)
    vm = VirtualBox::VM.find( vmname )
    @@current = vm.current_snapshot
    return unless @@current
    new(vm.root_snapshot).walk
    end
    end

    def initialize(snap)
    @snap = snap
    self.class.snaps << self
    end
    def current?
    snap.uuid == @@current.uuid
    end
    def register
    end
    attr_reader :snap

    def have_child?
    ! @snap.children.empty?
    end

    def first_child
    snap.children.first
    end

    def walk
    if have_child?
    s = self.class.new first_child
    s.walk
    end
    end
    end
    end

    class Command < Vagrant::Command::GroupBase
    register "snap","Manages a snap"

    no_tasks {
    def vmname
    @vagrant_env ||= Vagrant::Environment.new
    @instance_name ||= "#{@vagrant_env.vms[:default].vm.name}"
    @instance_name
    end
    }

    desc "list", "list snapshot"
    def list
    format = " %s %-20s %s"
    VBox::SnapShot.parse_tree( vmname )
    result = VBox::SnapShot.snaps.map do |s|
    cur_mark = s.current? ? "*" : " "
    format % [ cur_mark, s.time_stamp.strftime("%Y%m%d-%H:%M:%S"), s.name ]
    end
    puts result
    end

    desc "go [SNAPNAME]", "go to specified snapshot"
    def go(snapshot_name)
    system "VBoxManage controlvm #{vmname} poweroff"
    system "VBoxManage snapshot #{vmname} restore #{snapshot_name}"
    system "VBoxManage startvm #{vmname} --type headless"
    end

    desc "back", "back to current snapshot"
    def back
    system "VBoxManage controlvm #{vmname} poweroff"
    system "VBoxManage snapshot #{vmname} restorecurrent"
    system "VBoxManage startvm #{vmname} --type headless"
    end

    desc "take", "take snapshot"
    def take
    VBox::SnapShot.parse_tree( vmname )
    last = VBox::SnapShot.snaps.last
    new_name = last ? last.name.succ : vmname + "-01"
    # new_name = last.name.succ
    if not last or VBox::SnapShot.is_endnode?
    system "VBoxManage snapshot #{vmname} take #{new_name} --pause"
    else
    puts "Can not create"
    end
    end

    desc "delete", "delete snapshot"
    def delete(snapshot_name)
    system "VBoxManage snapshot #{vmname} delete #{snapshot_name}"
    end
    end
    end