1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-26 09:57:23 +03:00

feature #3654: Add retry option to the recover API calls and onevm command

This commit is contained in:
Ruben S. Montero 2015-04-21 17:15:10 +02:00
parent 1b0f23e17d
commit b5da40364f
7 changed files with 182 additions and 157 deletions

View File

@ -129,6 +129,12 @@ public:
*/
void recover(VirtualMachine * vm, bool success);
/**
* Retries the last VM operation that lead to a failure. The underlying
* driver actions may be invoked and should be "re-entrant".
*/
void retry(VirtualMachine * vm);
private:
/**
* Thread id for the Virtual Machine Manager
@ -270,8 +276,6 @@ private:
void restart_action(int vid);
void retry_action(int vid);
void delete_action(int vid);
void clean_action(int vid);

View File

@ -349,7 +349,7 @@ public:
VirtualMachineRecover():
RequestManagerVirtualMachine("VirtualMachineRecover",
"Recovers a virtual machine",
"A:sib")
"A:sii")
{
auth_op = AuthRequest::ADMIN;
};

View File

@ -91,6 +91,12 @@ cmd=CommandParser::CmdParser.new(ARGV) do
:description => "Recover a VM by failing the pending action"
}
RETRY={
:name => "retry",
:large => "--retry",
:description => "Recover a VM by retrying the last failed action"
}
CLONETEMPLATE={
:name => "clonetemplate",
:short => "-c",
@ -530,27 +536,31 @@ cmd=CommandParser::CmdParser.new(ARGV) do
recover_desc = <<-EOT.unindent
Recovers a stuck VM that is waiting for a driver operation. The recovery
may be done by failing or succeeding the pending operation. YOU NEED
may be done by failing, succeeding or retrying the current operation. YOU NEED
TO MANUALLY CHECK THE VM STATUS ON THE HOST, to decide if the operation
was successful or not.
was successful or not, or if it can be retried.
Example: A VM is stuck in "migrate" because of a hardware failure. You
need to check if the VM is running in the new host or not to recover
the vm with --success or --failure, respectively.
States: Any ACTIVE state.
States for success/failure recovers: Any ACTIVE state.
States for a retry recover: Any *FAILURE state
EOT
command :recover, recover_desc, [:range,:vmid_list],
:options => [SUCCESS, FAILURE] do
:options => [SUCCESS, FAILURE, RETRY] do
if !options[:success].nil?
result = true
result = 1
elsif !options[:failure].nil?
result = false
result = 0
elsif !options[:retry].nil?
result = 2
else
STDERR.puts "Need to specify the result of the pending action."
STDERR.puts "\t--success recover the VM by succeeding the missing action."
STDERR.puts "\t--failure recover the VM by failing the missing action."
STDERR.puts "\t--retry recover the VM by retrying the last failed action."
exit -1
end

View File

@ -658,147 +658,6 @@ void LifeCycleManager::cancel_action(int vid)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::retry_action(int vid)
{
Nebula& nd = Nebula::instance();
TransferManager * tm = nd.get_tm();
VirtualMachineManager * vmm = nd.get_vmm();
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_state() != VirtualMachine::ACTIVE )
{
vm->unlock();
return;
}
VirtualMachine::LcmState state = vm->get_lcm_state();
switch (state)
{
case VirtualMachine::BOOT_FAILURE:
vm->set_state(VirtualMachine::BOOT);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is BOOT");
vmm->trigger(VirtualMachineManager::DEPLOY, vid);
break;
case VirtualMachine::BOOT_MIGRATE_FAILURE:
vm->set_state(VirtualMachine::BOOT_MIGRATE);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is BOOT_MIGRATE");
vmm->trigger(VirtualMachineManager::RESTORE, vid);
break;
case VirtualMachine::PROLOG_MIGRATE_FAILURE:
vm->set_state(VirtualMachine::PROLOG_MIGRATE);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is PROLOG_MIGRATE");
tm->trigger(TransferManager::PROLOG_MIGR, vid);
break;
case VirtualMachine::PROLOG_FAILURE:
vm->set_state(VirtualMachine::PROLOG);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is PROLOG.");
tm->trigger(TransferManager::PROLOG,vid);
break;
case VirtualMachine::EPILOG_FAILURE:
vm->set_state(VirtualMachine::EPILOG);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is EPILOG");
tm->trigger(TransferManager::EPILOG,vid);
break;
case VirtualMachine::EPILOG_STOP_FAILURE:
vm->set_state(VirtualMachine::EPILOG_STOP);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is EPILOG_STOP");
tm->trigger(TransferManager::EPILOG_STOP,vid);
break;
case VirtualMachine::EPILOG_UNDEPLOY_FAILURE:
vm->set_state(VirtualMachine::EPILOG_UNDEPLOY);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is EPILOG_UNDEPLOY");
tm->trigger(TransferManager::EPILOG_STOP,vid);
break;
case VirtualMachine::LCM_INIT:
case VirtualMachine::BOOT:
case VirtualMachine::BOOT_MIGRATE:
case VirtualMachine::BOOT_POWEROFF:
case VirtualMachine::BOOT_SUSPENDED:
case VirtualMachine::BOOT_STOPPED:
case VirtualMachine::BOOT_UNDEPLOY:
case VirtualMachine::BOOT_UNKNOWN:
case VirtualMachine::CANCEL:
case VirtualMachine::CLEANUP_RESUBMIT:
case VirtualMachine::CLEANUP_DELETE:
case VirtualMachine::EPILOG:
case VirtualMachine::EPILOG_STOP:
case VirtualMachine::EPILOG_UNDEPLOY:
case VirtualMachine::HOTPLUG:
case VirtualMachine::HOTPLUG_NIC:
case VirtualMachine::HOTPLUG_SNAPSHOT:
case VirtualMachine::HOTPLUG_SAVEAS:
case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF:
case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED:
case VirtualMachine::HOTPLUG_PROLOG_POWEROFF:
case VirtualMachine::HOTPLUG_EPILOG_POWEROFF:
case VirtualMachine::PROLOG:
case VirtualMachine::PROLOG_MIGRATE:
case VirtualMachine::PROLOG_RESUME:
case VirtualMachine::PROLOG_UNDEPLOY:
case VirtualMachine::MIGRATE:
case VirtualMachine::RUNNING:
case VirtualMachine::SAVE_STOP:
case VirtualMachine::SAVE_SUSPEND:
case VirtualMachine::SAVE_MIGRATE:
case VirtualMachine::SHUTDOWN:
case VirtualMachine::SHUTDOWN_POWEROFF:
case VirtualMachine::SHUTDOWN_UNDEPLOY:
case VirtualMachine::UNKNOWN:
break;
}
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::restart_action(int vid)
{
@ -1419,3 +1278,134 @@ void LifeCycleManager::recover(VirtualMachine * vm, bool success)
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::retry(VirtualMachine * vm)
{
Nebula& nd = Nebula::instance();
TransferManager * tm = nd.get_tm();
VirtualMachineManager * vmm = nd.get_vmm();
int vid = vm->get_oid();
if ( vm->get_state() != VirtualMachine::ACTIVE )
{
return;
}
VirtualMachine::LcmState state = vm->get_lcm_state();
switch (state)
{
case VirtualMachine::BOOT_FAILURE:
vm->set_state(VirtualMachine::BOOT);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is BOOT");
vmm->trigger(VirtualMachineManager::DEPLOY, vid);
break;
case VirtualMachine::BOOT_MIGRATE_FAILURE:
vm->set_state(VirtualMachine::BOOT_MIGRATE);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is BOOT_MIGRATE");
vmm->trigger(VirtualMachineManager::RESTORE, vid);
break;
case VirtualMachine::PROLOG_MIGRATE_FAILURE:
vm->set_state(VirtualMachine::PROLOG_MIGRATE);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is PROLOG_MIGRATE");
tm->trigger(TransferManager::PROLOG_MIGR, vid);
break;
case VirtualMachine::PROLOG_FAILURE:
vm->set_state(VirtualMachine::PROLOG);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is PROLOG.");
tm->trigger(TransferManager::PROLOG,vid);
break;
case VirtualMachine::EPILOG_FAILURE:
vm->set_state(VirtualMachine::EPILOG);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is EPILOG");
tm->trigger(TransferManager::EPILOG,vid);
break;
case VirtualMachine::EPILOG_STOP_FAILURE:
vm->set_state(VirtualMachine::EPILOG_STOP);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is EPILOG_STOP");
tm->trigger(TransferManager::EPILOG_STOP,vid);
break;
case VirtualMachine::EPILOG_UNDEPLOY_FAILURE:
vm->set_state(VirtualMachine::EPILOG_UNDEPLOY);
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is EPILOG_UNDEPLOY");
tm->trigger(TransferManager::EPILOG_STOP,vid);
break;
case VirtualMachine::LCM_INIT:
case VirtualMachine::BOOT:
case VirtualMachine::BOOT_MIGRATE:
case VirtualMachine::BOOT_POWEROFF:
case VirtualMachine::BOOT_SUSPENDED:
case VirtualMachine::BOOT_STOPPED:
case VirtualMachine::BOOT_UNDEPLOY:
case VirtualMachine::BOOT_UNKNOWN:
case VirtualMachine::CANCEL:
case VirtualMachine::CLEANUP_RESUBMIT:
case VirtualMachine::CLEANUP_DELETE:
case VirtualMachine::EPILOG:
case VirtualMachine::EPILOG_STOP:
case VirtualMachine::EPILOG_UNDEPLOY:
case VirtualMachine::HOTPLUG:
case VirtualMachine::HOTPLUG_NIC:
case VirtualMachine::HOTPLUG_SNAPSHOT:
case VirtualMachine::HOTPLUG_SAVEAS:
case VirtualMachine::HOTPLUG_SAVEAS_POWEROFF:
case VirtualMachine::HOTPLUG_SAVEAS_SUSPENDED:
case VirtualMachine::HOTPLUG_PROLOG_POWEROFF:
case VirtualMachine::HOTPLUG_EPILOG_POWEROFF:
case VirtualMachine::PROLOG:
case VirtualMachine::PROLOG_MIGRATE:
case VirtualMachine::PROLOG_RESUME:
case VirtualMachine::PROLOG_UNDEPLOY:
case VirtualMachine::MIGRATE:
case VirtualMachine::RUNNING:
case VirtualMachine::SAVE_STOP:
case VirtualMachine::SAVE_SUSPEND:
case VirtualMachine::SAVE_MIGRATE:
case VirtualMachine::SHUTDOWN:
case VirtualMachine::SHUTDOWN_POWEROFF:
case VirtualMachine::SHUTDOWN_UNDEPLOY:
case VirtualMachine::UNKNOWN:
break;
}
return;
}

View File

@ -483,12 +483,13 @@ public class VirtualMachine extends PoolElement{
*
* @param client XML-RPC Client.
* @param id The virtual machine id (vid) of the target instance.
* @param success recover by succeeding the missing transaction if true.
* @param operation to recover the VM: (0) failure, (1) success or (2)
* retry
* @return If an error occurs the error message contains the reason.
*/
public static OneResponse recover(Client client, int id, boolean success)
public static OneResponse recover(Client client, int id, int operation)
{
return client.call(RECOVER, id, success);
return client.call(RECOVER, id, operation);
}
// =================================

View File

@ -596,7 +596,8 @@ module OpenNebula
# Recovers an ACTIVE VM
#
# @param result [Boolean] Recover with success (true) or failure (false)
# @param result [Integer] Recover with failure (0), success (1) or
# retry (2)
# @param result [info] Additional information needed to recover the VM
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise

View File

@ -2249,8 +2249,8 @@ void VirtualMachineDetachNic::request_execute(
void VirtualMachineRecover::request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att)
{
int id = xmlrpc_c::value_int(paramList.getInt(1));
bool success = xmlrpc_c::value_boolean(paramList.getBoolean(2));
int id = xmlrpc_c::value_int(paramList.getInt(1));
int op = xmlrpc_c::value_int(paramList.getInt(2));
VirtualMachine * vm;
@ -2277,7 +2277,26 @@ void VirtualMachineRecover::request_execute(
return;
}
lcm->recover(vm, success);
switch (op)
{
case 0:
lcm->recover(vm, false);
break;
case 1:
lcm->recover(vm, true);
break;
case 2:
lcm->retry(vm);
break;
default:
failure_response(ACTION,
request_error("Wrong recovery operation code",""),
att);
vm->unlock();
return;
}
success_response(id, att);