Skip to content

Commit

Permalink
Merge pull request #296 from Sharpie/add-snapshot-support
Browse files Browse the repository at this point in the history
Add snapshot support
  • Loading branch information
ggiamarchi authored Mar 2, 2017
2 parents 876ad73 + 12ab906 commit d91b1cb
Show file tree
Hide file tree
Showing 12 changed files with 364 additions and 7 deletions.
1 change: 1 addition & 0 deletions source/.rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ AllCops:
- '.bundle/**/*'
- 'out/**/*'
- '**/Vagrantfile'
DisplayCopNames: true

Style/FileName:
Enabled: false
Expand Down
82 changes: 82 additions & 0 deletions source/lib/vagrant-openstack-provider/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def self.action_destroy
b2.use Message, I18n.t('vagrant_openstack.not_created')
else
b2.use(ProvisionerCleanup, :before)
b2.use SnapshotCleanup if Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.8.0')
b2.use DeleteServer
b2.use DeleteStack
end
Expand Down Expand Up @@ -233,6 +234,77 @@ def self.action_reload
end
end

# TODO: Remove the if guard when Vagrant 1.8.0 is the minimum version.
# rubocop:disable IndentationWidth
if Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.8.0')
def self.action_snapshot_delete
new_builder.tap do |b|
b.use ConfigValidate
b.use ConnectOpenstack
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use Message, I18n.t('vagrant_openstack.not_created')
else
b2.use SnapshotDelete
end
end
end
end

def self.action_snapshot_list
new_builder.tap do |b|
b.use ConfigValidate
b.use ConnectOpenstack
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use Message, I18n.t('vagrant_openstack.not_created')
else
b2.use SnapshotList
end
end
end
end

def self.action_snapshot_restore
new_builder.tap do |b|
b.use ConfigValidate
b.use ConnectOpenstack
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use Message, I18n.t('vagrant_openstack.not_created')
next
end

b2.use SnapshotRestore
b2.use WaitForServerToBeActive
b2.use WaitForCommunicator

b2.use Call, IsEnvSet, :snapshot_delete do |env2, b3|
# Used by vagrant push/pop
b3.use action_snapshot_delete if env2[:result]
end

b2.use action_provision
end
end
end

def self.action_snapshot_save
new_builder.tap do |b|
b.use ConfigValidate
b.use ConnectOpenstack
b.use Call, IsState, :not_created do |env, b2|
if env[:result]
b2.use Message, I18n.t('vagrant_openstack.not_created')
else
b2.use SnapshotSave
end
end
end
end
end # Vagrant > 1.8.0 guard
# rubocop:enable IndentationWidth

# The autoload farm
action_root = Pathname.new(File.expand_path('../action', __FILE__))
autoload :Message, action_root.join('message')
Expand All @@ -251,6 +323,16 @@ def self.action_reload
autoload :ProvisionWrapper, action_root.join('provision')
autoload :WaitForServerToStop, action_root.join('wait_stop')
autoload :WaitForServerToBeActive, action_root.join('wait_active')
# TODO: Remove the if guard when Vagrant 1.8.0 is the minimum version.
# rubocop:disable IndentationWidth
if Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.8.0')
autoload :SnapshotCleanup, action_root.join('snapshot_cleanup')
autoload :SnapshotDelete, action_root.join('snapshot_delete')
autoload :SnapshotList, action_root.join('snapshot_list')
autoload :SnapshotRestore, action_root.join('snapshot_restore')
autoload :SnapshotSave, action_root.join('snapshot_save')
end
# rubocop:enable IndentationWidth

private

Expand Down
32 changes: 32 additions & 0 deletions source/lib/vagrant-openstack-provider/action/snapshot_cleanup.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'vagrant-openstack-provider/action/abstract_action'

module VagrantPlugins
module Openstack
module Action
class SnapshotCleanup < AbstractAction
def initialize(app, _env)
@app = app
end

def call(env)
nova = env[:openstack_client].nova
machine_snapshots = nova.list_snapshots(env, env[:machine].id)

snapshots_to_clean = machine_snapshots.select do |s|
s.metadata.key?('vagrant_snapshot')
end

@app.call env

unless snapshots_to_clean.empty?
env[:ui].info("Deleting Vagrant snapshots: #{snapshots_to_clean.map(&:name)}")
end

snapshots_to_clean.each do |s|
nova.delete_snapshot(env, s.id)
end
end
end
end
end
end
32 changes: 32 additions & 0 deletions source/lib/vagrant-openstack-provider/action/snapshot_delete.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'vagrant-openstack-provider/action/abstract_action'

module VagrantPlugins
module Openstack
module Action
class SnapshotDelete < AbstractAction
def initialize(app, _env)
@app = app
end

def call(env)
nova = env[:openstack_client].nova
machine_snapshots = nova.list_snapshots(env, env[:machine].id)

snapshot = machine_snapshots.find { |s| s.name == env[:snapshot_name] }

unless snapshot.nil?
env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.deleting',
name: snapshot.name))

nova.delete_snapshot(env, snapshot.id)

env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.deleted',
name: snapshot.name))
end

@app.call env
end
end
end
end
end
22 changes: 22 additions & 0 deletions source/lib/vagrant-openstack-provider/action/snapshot_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'vagrant-openstack-provider/action/abstract_action'

module VagrantPlugins
module Openstack
module Action
class SnapshotList < AbstractAction
def initialize(app, _env)
@app = app
end

def call(env)
nova = env[:openstack_client].nova
machine_snapshots = nova.list_snapshots(env, env[:machine].id)

env[:machine_snapshot_list] = machine_snapshots.map(&:name)

@app.call env
end
end
end
end
end
29 changes: 29 additions & 0 deletions source/lib/vagrant-openstack-provider/action/snapshot_restore.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require 'vagrant-openstack-provider/action/abstract_action'

module VagrantPlugins
module Openstack
module Action
class SnapshotRestore < AbstractAction
def initialize(app, _env)
@app = app
end

def call(env)
nova = env[:openstack_client].nova
machine_snapshots = nova.list_snapshots(env, env[:machine].id)

snapshot = machine_snapshots.find { |s| s.name == env[:snapshot_name] }

unless snapshot.nil?
env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.restoring',
name: snapshot.name))

nova.restore_snapshot(env, env[:machine].id, snapshot.id)
end

@app.call env
end
end
end
end
end
51 changes: 51 additions & 0 deletions source/lib/vagrant-openstack-provider/action/snapshot_save.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require 'vagrant-openstack-provider/action/abstract_action'

module VagrantPlugins
module Openstack
module Action
class SnapshotSave < AbstractAction
def initialize(app, _env, retry_interval = 3)
@app = app
@retry_interval = retry_interval
end

def call(env)
nova = env[:openstack_client].nova
config = env[:machine].provider_config

env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.saving',
name: env[:snapshot_name]))

nova.create_snapshot(
env,
env[:machine].id, env[:snapshot_name])

image = nova.list_snapshots(env, env[:machine].id).find { |i| i.name == env[:snapshot_name] }

timeout(config.server_create_timeout, Errors::Timeout) do
loop do
image_status = nova.get_image_details(env, image.id)

break if image_status['status'] == 'ACTIVE'

unless image_status['progress'].nil?
env[:ui].clear_line
env[:ui].report_progress(image_status['progress'], 100, false)
end

sleep @retry_interval
end
end

# Clear progress output.
env[:ui].clear_line

env[:ui].success(I18n.t('vagrant.actions.vm.snapshot.saved',
name: env[:snapshot_name]))

@app.call env
end
end
end
end
end
15 changes: 15 additions & 0 deletions source/lib/vagrant-openstack-provider/cap/snapshot_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module VagrantPlugins
module Openstack
module Cap
module SnapshotList
# Returns a list of the snapshots that are taken on this machine.
#
# @return [Array<String>]
def self.snapshot_list(machine)
env = machine.action(:snapshot_list, lock: false)
env[:machine_snapshot_list]
end
end
end
end
end
8 changes: 6 additions & 2 deletions source/lib/vagrant-openstack-provider/client/domain.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,23 @@ class Image < Item
attr_accessor :size
attr_accessor :min_ram
attr_accessor :min_disk
attr_accessor :metadata

def initialize(id, name, visibility = nil, size = nil, min_ram = nil, min_disk = nil)
# rubocop:disable Metrics/ParameterLists
def initialize(id, name, visibility = nil, size = nil, min_ram = nil, min_disk = nil, metadata = {})
@visibility = visibility
@size = size
@min_ram = min_ram
@min_disk = min_disk
@metadata = metadata
super(id, name)
end
# rubocop:enable Metrics/ParameterLists

protected

def state
[@id, @name, @visibility, @size, @min_ram, @min_disk]
[@id, @name, @visibility, @size, @min_ram, @min_disk, @metadata]
end
end

Expand Down
Loading

0 comments on commit d91b1cb

Please sign in to comment.