diff --git a/include/DispatchManager.h b/include/DispatchManager.h index b9d5e94cdd..0bbc488f1d 100644 --- a/include/DispatchManager.h +++ b/include/DispatchManager.h @@ -210,6 +210,15 @@ public: int resubmit( int vid); + /** + * Reboots a VM preserving any resource and RUNNING state + * @param vid VirtualMachine identification + * @return 0 on success, -1 if the VM does not exits or -2 if the VM is + * in a wrong a state + */ + int reboot( + int vid); + private: /** * Thread id for the Dispatch Manager diff --git a/include/LifeCycleManager.h b/include/LifeCycleManager.h index 4ad0986836..4206bbd51c 100644 --- a/include/LifeCycleManager.h +++ b/include/LifeCycleManager.h @@ -67,6 +67,7 @@ public: LIVE_MIGRATE, /**< Sent by the DM to live-migrate a VM */ SHUTDOWN, /**< Sent by the DM to shutdown a running VM */ RESTART, /**< Sent by the DM to restart a deployed VM */ + REBOOT, /**< Sent by the DM to reboot a running VM */ DELETE, /**< Sent by the DM to delete a VM */ CLEAN, /**< Sent by the DM to cleanup a VM for resubmission*/ FINALIZE @@ -194,6 +195,8 @@ private: void restart_action(int vid); + void reboot_action(int vid); + void delete_action(int vid); void clean_action(int vid); diff --git a/include/VirtualMachineManager.h b/include/VirtualMachineManager.h index cab1799800..8f481973d6 100644 --- a/include/VirtualMachineManager.h +++ b/include/VirtualMachineManager.h @@ -51,6 +51,7 @@ public: CANCEL_PREVIOUS, MIGRATE, RESTORE, + REBOOT, POLL, TIMER, DRIVER_CANCEL, @@ -262,6 +263,13 @@ private: void restore_action( int vid); + /** + * Reboots a running VM. + * @param vid the id of the VM. + */ + void reboot_action( + int vid); + /** * Polls a VM. * @param vid the id of the VM. diff --git a/include/VirtualMachineManagerDriver.h b/include/VirtualMachineManagerDriver.h index 2d75485ed4..c37c63e28e 100644 --- a/include/VirtualMachineManagerDriver.h +++ b/include/VirtualMachineManagerDriver.h @@ -127,6 +127,15 @@ private: const int oid, const string& drv_msg) const; + /** + * Sends a reboot request to the MAD: "REBOOT ID XML_DRV_MSG" + * @param oid the virtual machine id. + * @param drv_msg xml data for the mad operation + */ + void reboot ( + const int oid, + const string& drv_msg) const; + /** * Sends a cancel request to the MAD: "CANCEL ID XML_DRV_MSG" * @param oid the virtual machine id. diff --git a/install.sh b/install.sh index 1abc401669..da629029a0 100755 --- a/install.sh +++ b/install.sh @@ -587,6 +587,7 @@ VMM_EXEC_KVM_SCRIPTS="src/vmm_mad/remotes/kvm/cancel \ src/vmm_mad/remotes/kvm/migrate \ src/vmm_mad/remotes/kvm/migrate_local \ src/vmm_mad/remotes/kvm/restore \ + src/vmm_mad/remotes/kvm/reboot \ src/vmm_mad/remotes/kvm/save \ src/vmm_mad/remotes/kvm/poll \ src/vmm_mad/remotes/kvm/poll_ganglia \ @@ -601,6 +602,7 @@ VMM_EXEC_XEN_SCRIPTS="src/vmm_mad/remotes/xen/cancel \ src/vmm_mad/remotes/xen/xenrc \ src/vmm_mad/remotes/xen/migrate \ src/vmm_mad/remotes/xen/restore \ + src/vmm_mad/remotes/xen/reboot \ src/vmm_mad/remotes/xen/save \ src/vmm_mad/remotes/xen/poll \ src/vmm_mad/remotes/xen/poll_ganglia \ diff --git a/src/cli/onevm b/src/cli/onevm index 3cd90e80ec..d94455657e 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -182,6 +182,19 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + reboot_desc = <<-EOT.unindent + Reboots the given VM, this is equivalent to execute the reboot command + from the VM console. + + States: RUNNING + EOT + + command :reboot, reboot_desc, [:range,:vmid_list] do + helper.perform_actions(args[0],options,"rebooting") do |vm| + vm.reboot + end + end + deploy_desc = <<-EOT.unindent Deploys the given VM in the specified Host. This command forces the deployment, in a standard installation the Scheduler is in charge diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 37189b4a81..b728bd0e06 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -539,6 +539,50 @@ error: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int DispatchManager::reboot(int vid) +{ + VirtualMachine * vm; + ostringstream oss; + + vm = vmpool->get(vid,true); + + if ( vm == 0 ) + { + return -1; + } + + oss << "Rebooting VM " << vid; + NebulaLog::log("DiM",Log::DEBUG,oss); + + if (vm->get_state() == VirtualMachine::ACTIVE && + vm->get_lcm_state() == VirtualMachine::RUNNING ) + { + Nebula& nd = Nebula::instance(); + LifeCycleManager * lcm = nd.get_lcm(); + + lcm->trigger(LifeCycleManager::REBOOT,vid); + } + else + { + goto error; + } + + vm->unlock(); + + return 0; + +error: + oss.str(""); + oss << "Could not reboot VM " << vid << ", wrong state."; + NebulaLog::log("DiM",Log::ERROR,oss); + + vm->unlock(); + + return -2; +} +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + int DispatchManager::finalize( int vid) { diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index c415692bed..0366f5fa5b 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -427,6 +427,37 @@ void LifeCycleManager::cancel_action(int vid) return; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void LifeCycleManager::reboot_action(int vid) +{ + VirtualMachine * vm; + + vm = vmpool->get(vid,true); + + if ( vm == 0 ) + { + return; + } + + if (vm->get_state() == VirtualMachine::ACTIVE && + vm->get_lcm_state() == VirtualMachine::RUNNING) + { + Nebula& nd = Nebula::instance(); + VirtualMachineManager * vmm = nd.get_vmm(); + + vmm->trigger(VirtualMachineManager::REBOOT,vid); + } + else + { + vm->log("LCM", Log::ERROR, "reboot_action, VM in a wrong state."); + } + + vm->unlock(); + + return; +} /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ diff --git a/src/lcm/LifeCycleManager.cc b/src/lcm/LifeCycleManager.cc index cd8c4c5f12..8e6e3018ea 100644 --- a/src/lcm/LifeCycleManager.cc +++ b/src/lcm/LifeCycleManager.cc @@ -165,6 +165,10 @@ void LifeCycleManager::trigger(Actions action, int _vid) aname = "RESTART"; break; + case REBOOT: + aname = "REBOOT"; + break; + case DELETE: aname = "DELETE"; break; @@ -298,6 +302,10 @@ void LifeCycleManager::do_action(const string &action, void * arg) { restart_action(vid); } + else if (action == "REBOOT") + { + reboot_action(vid); + } else if (action == "DELETE") { delete_action(vid); diff --git a/src/mad/ruby/OpenNebulaDriver.rb b/src/mad/ruby/OpenNebulaDriver.rb index 18561f1fc7..eaaa3051fb 100644 --- a/src/mad/ruby/OpenNebulaDriver.rb +++ b/src/mad/ruby/OpenNebulaDriver.rb @@ -87,7 +87,7 @@ class OpenNebulaDriver < ActionManager :ssh_stream => nil }.merge(ops) - params = parameters+" #{id} #{host}" + params = parameters + " #{id} #{host}" command = action_command_line(aname, params, options[:script_name]) if action_is_local?(aname) diff --git a/src/mad/ruby/VirtualMachineDriver.rb b/src/mad/ruby/VirtualMachineDriver.rb index f9f5fc1c21..11a419baee 100644 --- a/src/mad/ruby/VirtualMachineDriver.rb +++ b/src/mad/ruby/VirtualMachineDriver.rb @@ -36,6 +36,7 @@ class VirtualMachineDriver < OpenNebulaDriver ACTION = { :deploy => "DEPLOY", :shutdown => "SHUTDOWN", + :reboot => "REBOOT", :cancel => "CANCEL", :save => "SAVE", :restore => "RESTORE", @@ -80,6 +81,7 @@ class VirtualMachineDriver < OpenNebulaDriver register_action(ACTION[:deploy].to_sym, method("deploy")) register_action(ACTION[:shutdown].to_sym, method("shutdown")) + register_action(ACTION[:reboot].to_sym, method("reboot")) register_action(ACTION[:cancel].to_sym, method("cancel")) register_action(ACTION[:save].to_sym, method("save")) register_action(ACTION[:restore].to_sym, method("restore")) @@ -119,6 +121,11 @@ class VirtualMachineDriver < OpenNebulaDriver send_message(ACTION[:shutdown],RESULT[:failure],id,error) end + def reboot(id, drv_message) + error = "Action not implemented by driver #{self.class}" + send_message(ACTION[:reboot],RESULT[:failure],id,error) + end + def cancel(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:cancel],RESULT[:failure],id,error) 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 ccb89f254d..2660b4d9ac 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -248,6 +248,7 @@ public class VirtualMachine extends PoolElement{ * It is recommended to use the helper methods instead: * * * @param action The action name to be performed, can be:
- * "shutdown", "hold", "release", "stop", "cancel", "suspend", + * "shutdown", "reboot", "hold", "release", "stop", "cancel", "suspend", * "resume", "restart", "finalize". * @return If an error occurs the error message contains the reason. */ @@ -357,6 +358,15 @@ public class VirtualMachine extends PoolElement{ return action("shutdown"); } + /** + * Reboots a running VM. + * @return If an error occurs the error message contains the reason. + */ + public OneResponse reboot() + { + return action("reboot"); + } + /** * Cancels the running VM. * @return If an error occurs the error message contains the reason. diff --git a/src/oca/ruby/OpenNebula/VirtualMachine.rb b/src/oca/ruby/OpenNebula/VirtualMachine.rb index 8e708ff9ff..1690e210c1 100644 --- a/src/oca/ruby/OpenNebula/VirtualMachine.rb +++ b/src/oca/ruby/OpenNebula/VirtualMachine.rb @@ -143,6 +143,11 @@ module OpenNebula action('shutdown') end + # Shutdowns an already deployed VM + def reboot + action('reboot') + end + # Cancels a running VM def cancel action('cancel') diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 9d4aacd84b..451eb8edd2 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -233,6 +233,10 @@ void VirtualMachineAction::request_execute(xmlrpc_c::paramList const& paramList, { rc = dm->resubmit(id); } + else if (action == "reboot") + { + rc = dm->reboot(id); + } switch (rc) { diff --git a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb index d00c0efc32..3da1ca9f9a 100644 --- a/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb +++ b/src/sunstone/models/OpenNebulaJSON/VirtualMachineJSON.rb @@ -62,6 +62,7 @@ module OpenNebulaJSON when "restart" then self.restart when "saveas" then self.save_as(action_hash['params']) when "shutdown" then self.shutdown + when "reboot" then self.reboot when "resubmit" then self.resubmit when "chown" then self.chown(action_hash['params']) else diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc index 94706f35f8..ae5b70a7a7 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -126,6 +126,10 @@ void VirtualMachineManager::trigger(Actions action, int _vid) aname = "RESTORE"; break; + case REBOOT: + aname = "REBOOT"; + break; + case SHUTDOWN: aname = "SHUTDOWN"; break; @@ -198,6 +202,10 @@ void VirtualMachineManager::do_action(const string &action, void * arg) { restore_action(vid); } + else if (action == "REBOOT") + { + reboot_action(vid); + } else if (action == "SHUTDOWN") { shutdown_action(vid); @@ -573,6 +581,75 @@ error_common: /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +void VirtualMachineManager::reboot_action( + int vid) +{ + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + string vm_tmpl; + string * drv_msg; + ostringstream os; + + // Get the VM from the pool + vm = vmpool->get(vid,true); + + if (vm == 0) + { + return; + } + + if (!vm->hasHistory()) + { + goto error_history; + } + + // Get the driver for this VM + vmd = get(vm->get_vmm_mad()); + + if ( vmd == 0 ) + { + goto error_driver; + } + + // Invoke driver method + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->reboot(vid, *drv_msg); + + delete drv_msg; + + vm->unlock(); + + return; + +error_history: + os.str(""); + os << "reboot_action, VM has no history"; + goto error_common; + +error_driver: + os.str(""); + os << "reboot_action, error getting driver " << vm->get_vmm_mad(); + +error_common: + vm->log("VMM", Log::ERROR, os); + vm->unlock(); + return; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + void VirtualMachineManager::cancel_action( int vid) { diff --git a/src/vmm/VirtualMachineManagerDriver.cc b/src/vmm/VirtualMachineManagerDriver.cc index d20db0f5e0..8b4298c158 100644 --- a/src/vmm/VirtualMachineManagerDriver.cc +++ b/src/vmm/VirtualMachineManagerDriver.cc @@ -211,6 +211,20 @@ void VirtualMachineManagerDriver::poll ( write(os); }; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineManagerDriver::reboot ( + const int oid, + const string& drv_msg) const +{ + ostringstream os; + + os << "REBOOT " << oid << " " << drv_msg << endl; + + write(os); +}; + /* ************************************************************************** */ /* MAD Interface */ /* ************************************************************************** */ @@ -424,6 +438,18 @@ void VirtualMachineManagerDriver::protocol( lcm->trigger(LifeCycleManager::DEPLOY_FAILURE, id); } } + else if ( action == "REBOOT" ) + { + if (result == "SUCCESS") + { + vm->log("VMM",Log::ERROR,"VM Successfully rebooted."); + } + else + { + log_error(vm,os,is,"Error rebooting VM, assume it's still running"); + vmpool->update(vm); + } + } else if ( action == "POLL" ) { if (result == "SUCCESS") diff --git a/src/vmm_mad/dummy/one_vmm_dummy.rb b/src/vmm_mad/dummy/one_vmm_dummy.rb index f424a12c13..a515e47295 100755 --- a/src/vmm_mad/dummy/one_vmm_dummy.rb +++ b/src/vmm_mad/dummy/one_vmm_dummy.rb @@ -52,6 +52,10 @@ class DummyDriver < VirtualMachineDriver send_message(ACTION[:shutdown],RESULT[:success],id) end + def reboot(id, drv_message) + send_message(ACTION[:reboot],RESULT[:success],id) + end + def cancel(id, drv_message) send_message(ACTION[:cancel],RESULT[:success],id) end diff --git a/src/vmm_mad/ec2/one_vmm_ec2.rb b/src/vmm_mad/ec2/one_vmm_ec2.rb index f5346e58f9..78d078ad3a 100755 --- a/src/vmm_mad/ec2/one_vmm_ec2.rb +++ b/src/vmm_mad/ec2/one_vmm_ec2.rb @@ -52,6 +52,7 @@ class EC2Driver < VirtualMachineDriver :terminate => "#{EC2_LOCATION}/bin/ec2-terminate-instances", :describe => "#{EC2_LOCATION}/bin/ec2-describe-instances", :associate => "#{EC2_LOCATION}/bin/ec2-associate-address", + :reboot => "#{EC2_LOCATION}/bin/ec2-reboot-instances", :authorize => "#{EC2_LOCATION}/bin/ec2-authorize" } @@ -186,6 +187,20 @@ class EC2Driver < VirtualMachineDriver ec2_terminate(ACTION[:shutdown], id, deploy_id) end + + # Reboot a EC2 instance + def reboot(id, drv_message) + cmd = "#{EC2_LOCATION}/bin/ec2-reboot-instances #{deploy_id}" + exe = LocalCommand.run(cmd, log_method(id)) + + if exe.code != 0 + result = RESULT[:failure] + else + result = RESULT[:success] + end + + send_message(action,result,id) + end # Cancel a EC2 instance def cancel(id, drv_message) diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb index 4b854a697a..6f44895e0e 100755 --- a/src/vmm_mad/exec/one_vmm_exec.rb +++ b/src/vmm_mad/exec/one_vmm_exec.rb @@ -450,12 +450,23 @@ class ExecDriver < VirtualMachineDriver # POLL action, gets information of a VM # def poll(id, drv_message) - data = decode(drv_message) - host = data.elements['HOST'].text - deploy_id = data.elements['DEPLOY_ID'].text + data = decode(drv_message) + host = data.elements['HOST'].text + deploy_id = data.elements['DEPLOY_ID'].text do_action("#{deploy_id} #{host}", id, host, ACTION[:poll]) end + + # + # REBOOT action, reboots a running VM + # + def reboot(id, drv_message) + data = decode(drv_message) + host = data.elements['HOST'].text + deploy_id = data.elements['DEPLOY_ID'].text + + do_action("#{deploy_id} #{host}", id, host, ACTION[:reboot]) + end end ################################################################################ diff --git a/src/vmm_mad/exec/one_vmm_sh b/src/vmm_mad/exec/one_vmm_sh index 6db516936c..7b7425d690 100755 --- a/src/vmm_mad/exec/one_vmm_sh +++ b/src/vmm_mad/exec/one_vmm_sh @@ -22,4 +22,4 @@ else MAD_LOCATION=$ONE_LOCATION/lib/mads fi -exec $MAD_LOCATION/one_vmm_exec -l deploy,shutdown,cancel,save,restore,migrate,poll,pre,post,clean $* +exec $MAD_LOCATION/one_vmm_exec -l deploy,shutdown,reboot,cancel,save,restore,migrate,poll,pre,post,clean $* diff --git a/src/vmm_mad/remotes/kvm/reboot b/src/vmm_mad/remotes/kvm/reboot new file mode 100755 index 0000000000..bac3929fca --- /dev/null +++ b/src/vmm_mad/remotes/kvm/reboot @@ -0,0 +1,27 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh + +deploy_id=$1 + +exec_and_log "virsh --connect $LIBVIRT_URI reboot $deploy_id" \ + "Could not reboot domain $deploy_id" + +exit 0 diff --git a/src/vmm_mad/remotes/xen/reboot b/src/vmm_mad/remotes/xen/reboot new file mode 100755 index 0000000000..c662c6b07c --- /dev/null +++ b/src/vmm_mad/remotes/xen/reboot @@ -0,0 +1,24 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +source $(dirname $0)/xenrc +source $(dirname $0)/../../scripts_common.sh + +deploy_id=$1 + +exec_and_log "$XM_REBOOT $deploy_id" "Could not reboot domain $deploy_id" diff --git a/src/vmm_mad/remotes/xen/xenrc b/src/vmm_mad/remotes/xen/xenrc index 1337e6e77b..713afe4b3c 100644 --- a/src/vmm_mad/remotes/xen/xenrc +++ b/src/vmm_mad/remotes/xen/xenrc @@ -22,6 +22,7 @@ export XM_CREATE="sudo $XM_PATH create" export XM_CREDITS="sudo $XM_PATH sched-cred" export XM_MIGRATE="sudo $XM_PATH migrate -l" export XM_SAVE="sudo $XM_PATH save" +export XM_REBOOT="sudo $XM_PATH reboot" export XM_RESTORE="sudo $XM_PATH restore" export XM_LIST="sudo $XM_PATH list" export XM_SHUTDOWN="sudo $XM_PATH shutdown"