diff --git a/src/cli/onevm b/src/cli/onevm index 7c1611900a..fba094392c 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -79,6 +79,18 @@ cmd=CommandParser::CmdParser.new(ARGV) do :description => "Enforce that the host capacity is not exceeded" } + SUCCESS={ + :name => "success", + :large => "--success", + :description => "Recover a VM by succeeding the pending action" + } + + FAILURE={ + :name => "failure", + :large => "--failure", + :description => "Recover a VM by failing the pending action" + } + ######################################################################## # Global Options ######################################################################## @@ -501,6 +513,38 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + 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 + TO MANUALLY CHECK THE VM STATUS ON THE HOST, to decide if the operation + was successful or not. + + Example: A VM is stuck in "migrate" because of a harware failure. You + need to check if the VM is running in the new host or not to recover + the vm with success (onevm recover --with success) or failure + (onevm recover --with failure), respectively. + + States: Any ACTIVE state. + EOT + + command :recover, recover_desc, [:range,:vmid_list], + :options => [SUCCESS, FAILURE] do + if !options[:success].nil? + result = true + elsif !options[:failure].nil? + result = false + 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." + exit -1 + end + + helper.perform_actions(args[0], options, "recovering") do |vm| + vm.recover(result) + end + end + disk_attach_desc = <<-EOT.unindent Attaches a disk to a running VM diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index 96679c1a0f..3bdad77099 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -47,6 +47,7 @@ public class VirtualMachine extends PoolElement{ private static final String SNAPSHOTCREATE = METHOD_PREFIX + "snapshotcreate"; private static final String SNAPSHOTREVERT = METHOD_PREFIX + "snapshotrevert"; private static final String SNAPSHOTDELETE = METHOD_PREFIX + "snapshotdelete"; + private static final String RECOVER = METHOD_PREFIX + "recover"; private static final String[] VM_STATES = { @@ -438,7 +439,7 @@ public class VirtualMachine extends PoolElement{ } /** - * Deletes a VM snapshot + * Deletes a VM snapshot. * * @param client XML-RPC Client. * @param id The VM id of the target VM. @@ -450,6 +451,19 @@ public class VirtualMachine extends PoolElement{ return client.call(SNAPSHOTDELETE, id, snapId); } + /** + * Recovers a stuck VM. + * + * @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. + * @return If an error occurs the error message contains the reason. + */ + public static OneResponse recover(Client client, int id, boolean success) + { + return client.call(RECOVER, id, success); + } + // ================================= // Instanced object XML-RPC methods // ================================= @@ -817,6 +831,17 @@ public class VirtualMachine extends PoolElement{ return snapshotDelete(client, id, snapId); } + /** + * Recovers a stuck VM. + * + * @param success recover by succeeding the missing transaction if true. + * @return If an error occurs the error message contains the reason. + */ + public OneResponse recover(boolean success) + { + return recover(client, id, success); + } + // ================================= // Helpers // ================================= diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index c1855c2496..c1abbdb27c 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -43,7 +43,8 @@ module OpenNebula :snapshotdelete => "vm.snapshotdelete", :attachnic => "vm.attachnic", :detachnic => "vm.detachnic", - :resize => "vm.resize" + :resize => "vm.resize", + :recover => "vm.recover" } VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED @@ -524,9 +525,19 @@ module OpenNebula return call(VM_METHODS[:snapshotdelete], @pe_id, snap_id) end - ####################################################################### + # Recovers an ACTIVE VM + # + # @param result [Boolean] Recover with success (true) or failure (false) + # @param result [info] Additional information needed to recover the VM + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def recover(result) + return call(VM_METHODS[:recover], @pe_id, result) + end + + ######################################################################## # Helpers to get VirtualMachine information - ####################################################################### + ######################################################################## # Returns the VM state of the VirtualMachine (numeric value) def state