Ensure domain removal/halt limited to provider error (#1420)

Switch to dedicated actions to trigger destroy/halt via the recovery
mechanism if the VM bring up has failed to complete the bring up of the
machine.

Fixes: #1328
This commit is contained in:
Darragh Bailey
2021-12-04 16:55:50 +00:00
committed by GitHub
parent 380b3c2096
commit 1f9fd6dc2e
5 changed files with 204 additions and 67 deletions

View File

@@ -24,6 +24,8 @@ module VagrantPlugins
b.use ConfigValidate
b.use BoxCheckOutdated
b.use Call, IsCreated do |env, b2|
b2.use CleanupOnFailure
# Create VM if not yet created.
if !env[:result]
b2.use SetNameOfDomain
@@ -33,6 +35,8 @@ module VagrantPlugins
b2.use CreateNetworkInterfaces
b2.use action_start
b2.use SetupComplete
else
b2.use HandleStoragePool
b2.use HandleBox
@@ -51,6 +55,9 @@ module VagrantPlugins
b2.use CreateNetworks
b2.use action_start
end
# corresponding action to CleanupOnFailure
b2.use SetupComplete
end
end
end
@@ -327,6 +334,8 @@ module VagrantPlugins
action_root = Pathname.new(File.expand_path('../action', __FILE__))
autoload :PackageDomain, action_root.join('package_domain')
autoload :CleanupOnFailure, action_root.join('cleanup_on_failure')
autoload :SetupComplete, action_root.join('cleanup_on_failure')
autoload :CreateDomain, action_root.join('create_domain')
autoload :CreateDomainVolume, action_root.join('create_domain_volume')
autoload :CreateNetworkInterfaces, action_root.join('create_network_interfaces')

View File

@@ -0,0 +1,65 @@
# frozen_string_literal: true
module VagrantPlugins
module ProviderLibvirt
module Action
class CleanupOnFailure
def initialize(app, _env)
@logger = Log4r::Logger.new('vagrant_libvirt::action::cleanup_on_failure')
@app = app
end
def call(env)
env['vagrant-libvirt.provider'] = :starting
@app.call(env)
end
def recover(env)
return unless env[:machine] && env[:machine].state.id != :not_created
# only destroy if failed to complete bring up
if env['vagrant-libvirt.provider'] == :finished
@logger.info("VM completed provider setup, no need to teardown")
return
end
# If we're not supposed to destroy on error then just return
return unless env[:destroy_on_error]
if env[:halt_on_error]
halt_env = env.dup
halt_env.delete(:interrupted)
halt_env[:config_validate] = false
env[:action_runner].run(Action.action_halt, halt_env)
else
destroy_env = env.dup
destroy_env.delete(:interrupted)
destroy_env[:config_validate] = false
destroy_env[:force_confirm_destroy] = true
env[:action_runner].run(Action.action_destroy, destroy_env)
end
end
end
class SetupComplete
def initialize(app, _env)
@logger = Log4r::Logger.new('vagrant_libvirt::action::cleanup_on_failure')
@app = app
end
def call(env)
if env['vagrant-libvirt.provider'].nil?
raise Errors::CallChainError, require_action: CleanupOnFailure.name, current_action: SetupComplete.name
end
# mark provider as finished setup so that any failure after this
# point doesn't result in destroying or shutting down the VM
env['vagrant-libvirt.provider'] = :finished
@app.call(env)
end
end
end
end
end

View File

@@ -50,31 +50,6 @@ module VagrantPlugins
@app.call(env)
end
def recover(env)
# Undo the import
terminate(env)
end
def terminate(env)
if env[:machine].state.id != :not_created
# If we're not supposed to destroy on error then just return
return unless env[:destroy_on_error]
if env[:halt_on_error]
halt_env = env.dup
halt_env.delete(:interrupted)
halt_env[:config_validate] = false
env[:action_runner].run(Action.action_halt, halt_env)
else
destroy_env = env.dup
destroy_env.delete(:interrupted)
destroy_env[:config_validate] = false
destroy_env[:force_confirm_destroy] = true
env[:action_runner].run(Action.action_destroy, destroy_env)
end
end
end
end
end
end