1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-24 02:03:52 +03:00

Merge branch 'feature-1224'

Conflicts:
	include/RequestManagerVirtualMachine.h
	src/cli/one_helper/onevm_helper.rb
	src/oca/ruby/opennebula/virtual_machine.rb
	src/rm/RequestManager.cc
	src/rm/RequestManagerVirtualMachine.cc
This commit is contained in:
Ruben S. Montero 2013-02-28 03:19:04 +01:00
commit 84b633b42b
40 changed files with 1919 additions and 85 deletions

View File

@ -276,6 +276,50 @@ public:
int disk_id,
string& error_str);
/**
* Starts the snapshot create action
*
* @param vid VirtualMachine identification
* @param name Name for the new snapshot
* @param snap_id Will contain the new snapshot ID
* @param error_str Error reason, if any
*
* @return 0 on success, -1 otherwise
*/
int snapshot_create(
int vid,
string& name,
int& snap_id,
string& error_str);
/**
* Starts the snapshot revert action
*
* @param vid VirtualMachine identification
* @param snap_id Snapshot to be restored
* @param error_str Error reason, if any
*
* @return 0 on success, -1 otherwise
*/
int snapshot_revert(
int vid,
int snap_id,
string& error_str);
/**
* Starts the snapshot delete action
*
* @param vid VirtualMachine identification
* @param snap_id Snapshot to be deleted
* @param error_str Error reason, if any
*
* @return 0 on success, -1 otherwise
*/
int snapshot_delete(
int vid,
int snap_id,
string& error_str);
private:
/**
* Thread id for the Dispatch Manager

View File

@ -64,6 +64,12 @@ public:
DETACH_FAILURE, /**< Sent by the VMM when a detach action fails */
CLEANUP_SUCCESS, /**< Sent by the VMM when a cleanup action succeeds */
CLEANUP_FAILURE, /**< Sent by the VMM when a cleanup action fails */
SNAPSHOT_CREATE_SUCCESS, /**< Sent by the VMM on snap. create success */
SNAPSHOT_CREATE_FAILURE, /**< Sent by the VMM on snap. create failure */
SNAPSHOT_REVERT_SUCCESS, /**< Sent by the VMM on snap. revert success */
SNAPSHOT_REVERT_FAILURE, /**< Sent by the VMM on snap. revert failure */
SNAPSHOT_DELETE_SUCCESS, /**< Sent by the VMM on snap. revert success */
SNAPSHOT_DELETE_FAILURE, /**< Sent by the VMM on snap. revert failure */
DEPLOY, /**< Sent by the DM to deploy a VM on a host */
SUSPEND, /**< Sent by the DM to suspend an running VM */
RESTORE, /**< Sent by the DM to restore a suspended VM */
@ -189,6 +195,18 @@ private:
void cleanup_callback_action(int vid);
void snapshot_create_success(int vid);
void snapshot_create_failure(int vid);
void snapshot_revert_success(int vid);
void snapshot_revert_failure(int vid);
void snapshot_delete_success(int vid);
void snapshot_delete_failure(int vid);
void deploy_action(int vid);
void suspend_action(int vid);

View File

@ -232,7 +232,58 @@ public:
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualMachineSnapshotCreate: public RequestManagerVirtualMachine
{
public:
VirtualMachineSnapshotCreate():
RequestManagerVirtualMachine("VirtualMachineSnapshotCreate",
"Creates a new virtual machine snapshot",
"A:sis"){};
~VirtualMachineSnapshotCreate(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualMachineSnapshotRevert: public RequestManagerVirtualMachine
{
public:
VirtualMachineSnapshotRevert():
RequestManagerVirtualMachine("VirtualMachineSnapshotRevert",
"Reverts a virtual machine to a snapshot",
"A:sii"){};
~VirtualMachineSnapshotRevert(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualMachineSnapshotDelete: public RequestManagerVirtualMachine
{
public:
VirtualMachineSnapshotDelete():
RequestManagerVirtualMachine("VirtualMachineSnapshotDelete",
"Deletes a virtual machine snapshot",
"A:sii"){};
~VirtualMachineSnapshotDelete(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -89,7 +89,8 @@ public:
BOOT_POWEROFF = 20,
BOOT_SUSPENDED = 21,
BOOT_STOPPED = 22,
CLEANUP_DELETE = 23
CLEANUP_DELETE = 23,
HOTPLUG_SNAPSHOT = 24
};
// -------------------------------------------------------------------------
@ -953,6 +954,54 @@ public:
*/
int detach_failure();
// ------------------------------------------------------------------------
// Snapshot related functions
// ------------------------------------------------------------------------
/**
* Creates a new Snapshot attribute, and sets it to ACTIVE=YES
*
* @param name for the new Snapshot. If it is empty, the generated name
* will be placed in this param
* @param snap_id Id of the new snapshot
*
* @return 0 on success
*/
int new_snapshot(string& name, int& snap_id);
/**
* Sets the given Snapshot as ACTIVE=YES
*
* @param snap_id the snapshow ID
*
* @return 0 on success
*/
int set_active_snapshot(int snap_id);
/**
* Replaces HYPERVISOR_ID for the active SNAPSHOT
*
* @param hypervisor_id Id returned by the hypervisor for the newly
* created snapshot
*/
void update_snapshot_id(string& hypervisor_id);
/**
* Cleans the ACTIVE = YES attribute from the snapshots
*/
void clear_active_snapshot();
/**
* Deletes the SNAPSHOT that was in the process of being created
*/
void delete_active_snapshot();
/**
* Deletes all SNAPSHOT attributes
*/
void delete_snapshots();
private:
// -------------------------------------------------------------------------

View File

@ -61,7 +61,10 @@ public:
DRIVER_CANCEL,
FINALIZE,
ATTACH,
DETACH
DETACH,
SNAPSHOT_CREATE,
SNAPSHOT_REVERT,
SNAPSHOT_DELETE
};
/**
@ -332,6 +335,30 @@ private:
void detach_action(
int vid);
/**
* Creates a new system snapshot. The VM must have a snapshot with the
* attribute ACTIVE = YES
*
* @param vid the id of the VM.
*/
void snapshot_create_action(int vid);
/**
* Reverts to a snapshot. The VM must have a snapshot with the
* attribute ACTIVE = YES
*
* @param vid the id of the VM.
*/
void snapshot_revert_action(int vid);
/**
* Deletes a snapshot. The VM must have a snapshot with the
* attribute ACTIVE = YES
*
* @param vid the id of the VM.
*/
void snapshot_delete_action(int vid);
/**
* This function cancels the current driver operation
*/

View File

@ -298,6 +298,45 @@ private:
write_drv("DETACHDISK", oid, drv_msg);
}
/**
* Sends a snapshot create request to the MAD:
* "SNAPSHOTCREATE ID XML_DRV_MSG"
* @param oid the virtual machine id.
* @param drv_msg xml data for the mad operation
*/
void snapshot_create (
const int oid,
const string& drv_msg) const
{
write_drv("SNAPSHOTCREATE", oid, drv_msg);
}
/**
* Sends a snapshot revert request to the MAD:
* "SNAPSHOTREVERT ID XML_DRV_MSG"
* @param oid the virtual machine id.
* @param drv_msg xml data for the mad operation
*/
void snapshot_revert (
const int oid,
const string& drv_msg) const
{
write_drv("SNAPSHOTREVERT", oid, drv_msg);
}
/**
* Sends a snapshot delete request to the MAD:
* "SNAPSHOTDELETE ID XML_DRV_MSG"
* @param oid the virtual machine id.
* @param drv_msg xml data for the mad operation
*/
void snapshot_delete (
const int oid,
const string& drv_msg) const
{
write_drv("SNAPSHOTDELETE", oid, drv_msg);
}
void write_drv(const char * aname, const int oid, const string& msg) const
{
ostringstream os;

View File

@ -752,6 +752,9 @@ VMM_EXEC_KVM_SCRIPTS="src/vmm_mad/remotes/kvm/cancel \
src/vmm_mad/remotes/kvm/poll_ganglia \
src/vmm_mad/remotes/kvm/attach_disk \
src/vmm_mad/remotes/kvm/detach_disk \
src/vmm_mad/remotes/kvm/snapshot_create \
src/vmm_mad/remotes/kvm/snapshot_revert \
src/vmm_mad/remotes/kvm/snapshot_delete \
src/vmm_mad/remotes/kvm/shutdown"
#-------------------------------------------------------------------------------
@ -770,6 +773,9 @@ VMM_EXEC_XEN3_SCRIPTS="src/vmm_mad/remotes/xen/cancel \
src/vmm_mad/remotes/xen/poll_ganglia \
src/vmm_mad/remotes/xen/attach_disk \
src/vmm_mad/remotes/xen/detach_disk \
src/vmm_mad/remotes/xen/snapshot_create \
src/vmm_mad/remotes/xen/snapshot_revert \
src/vmm_mad/remotes/xen/snapshot_delete \
src/vmm_mad/remotes/xen/shutdown"
VMM_EXEC_XEN4_SCRIPTS="src/vmm_mad/remotes/xen/cancel \
@ -784,6 +790,9 @@ VMM_EXEC_XEN4_SCRIPTS="src/vmm_mad/remotes/xen/cancel \
src/vmm_mad/remotes/xen/poll_ganglia \
src/vmm_mad/remotes/xen/attach_disk \
src/vmm_mad/remotes/xen/detach_disk \
src/vmm_mad/remotes/xen/snapshot_create \
src/vmm_mad/remotes/xen/snapshot_revert \
src/vmm_mad/remotes/xen/snapshot_delete \
src/vmm_mad/remotes/xen/shutdown"
#-------------------------------------------------------------------------------
# VMM Driver VMWARE scripts, to be installed under $REMOTES_LOCATION/vmm/vmware
@ -792,6 +801,9 @@ VMM_EXEC_XEN4_SCRIPTS="src/vmm_mad/remotes/xen/cancel \
VMM_EXEC_VMWARE_SCRIPTS="src/vmm_mad/remotes/vmware/cancel \
src/vmm_mad/remotes/vmware/attach_disk \
src/vmm_mad/remotes/vmware/detach_disk \
src/vmm_mad/remotes/vmware/snapshot_create \
src/vmm_mad/remotes/vmware/snapshot_revert \
src/vmm_mad/remotes/vmware/snapshot_delete \
src/vmm_mad/remotes/vmware/scripts_common_sh.sh \
src/vmm_mad/remotes/vmware/deploy \
src/vmm_mad/remotes/vmware/migrate \

View File

@ -106,7 +106,8 @@
BOOT_POWEROFF = 20,
BOOT_SUSPENDED = 21,
BOOT_STOPPED = 22,
CLEANUP_DELETE = 23
CLEANUP_DELETE = 23,
HOTPLUG_SNAPSHOT = 24
-->
<xs:element name="LCM_STATE" type="xs:integer"/>
<xs:element name="RESCHED" type="xs:integer"/>

View File

@ -68,7 +68,8 @@
BOOT_POWEROFF = 20,
BOOT_SUSPENDED = 21,
BOOT_STOPPED = 22,
CLEANUP_DELETE = 23
CLEANUP_DELETE = 23,
HOTPLUG_SNAPSHOT = 24
-->
<xs:element name="LCM_STATE" type="xs:integer"/>
<xs:element name="RESCHED" type="xs:integer"/>

View File

@ -258,35 +258,6 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
}
puts
if vm.has_elements?("/VM/USER_TEMPLATE/SCHED_ACTION")
CLIHelper.print_header(str_h1 % "SCHEDULED ACTIONS",false)
CLIHelper::ShowTable.new(nil, self) do
column :"ID", "", :size=>2 do |d|
d["ID"] if !d.nil?
end
column :"ACTION", "", :left, :size=>10 do |d|
d["ACTION"] if !d.nil?
end
column :"SCHEDULED", "", :size=>12 do |d|
OpenNebulaHelper.time_to_str(d["TIME"], false) if !d.nil?
end
column :"DONE", "", :size=>12 do |d|
OpenNebulaHelper.time_to_str(d["DONE"], false) if !d.nil?
end
column :"MESSAGE", "", :left, :donottruncate, :size=>40 do |d|
d["MESSAGE"] if !d.nil?
end
end.show([vm.to_hash['VM']['USER_TEMPLATE']['SCHED_ACTION']].flatten, {})
puts
end
if vm.has_elements?("/VM/TEMPLATE/DISK")
CLIHelper.print_header(str_h1 % "VM DISKS",false)
CLIHelper::ShowTable.new(nil, self) do
@ -394,8 +365,69 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
puts
end
CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE TEMPLATE",false)
puts vm.template_str
if vm.has_elements?("/VM/TEMPLATE/SNAPSHOT")
CLIHelper.print_header(str_h1 % "SNAPSHOTS",false)
CLIHelper::ShowTable.new(nil, self) do
column :"ID", "", :size=>4 do |d|
d["SNAPSHOT_ID"] if !d.nil?
end
column :"TIME", "", :size=>12 do |d|
OpenNebulaHelper.time_to_str(d["TIME"], false) if !d.nil?
end
column :"NAME", "", :left, :size=>46 do |d|
d["NAME"] if !d.nil?
end
column :"HYPERVISOR_ID", "", :left, :size=>15 do |d|
d["HYPERVISOR_ID"] if !d.nil?
end
end.show([vm.to_hash['VM']['TEMPLATE']['SNAPSHOT']].flatten, {})
vm.delete_element("/VM/TEMPLATE/SNAPSHOT")
puts
end
if vm.has_elements?("/VM/HISTORY_RECORDS")
puts
CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE HISTORY",false)
format_history(vm)
end
if vm.has_elements?("/VM/USER_TEMPLATE/SCHED_ACTION")
CLIHelper.print_header(str_h1 % "SCHEDULED ACTIONS",false)
CLIHelper::ShowTable.new(nil, self) do
column :"ID", "", :size=>2 do |d|
d["ID"] if !d.nil?
end
column :"ACTION", "", :left, :size=>10 do |d|
d["ACTION"] if !d.nil?
end
column :"SCHEDULED", "", :size=>12 do |d|
OpenNebulaHelper.time_to_str(d["TIME"], false) if !d.nil?
end
column :"DONE", "", :size=>12 do |d|
OpenNebulaHelper.time_to_str(d["DONE"], false) if !d.nil?
end
column :"MESSAGE", "", :left, :donottruncate, :size=>40 do |d|
d["MESSAGE"] if !d.nil?
end
end.show([vm.to_hash['VM']['USER_TEMPLATE']['SCHED_ACTION']].flatten, {})
puts
end
if vm.has_elements?("/VM/USER_TEMPLATE")
puts
@ -408,12 +440,8 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
puts vm.template_like_str('USER_TEMPLATE')
end
if vm.has_elements?("/VM/HISTORY_RECORDS")
puts
CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE HISTORY",false)
format_history(vm)
end
CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE TEMPLATE",false)
puts vm.template_str
end
def format_history(vm)

View File

@ -631,10 +631,6 @@ cmd=CommandParser::CmdParser.new(ARGV) do
end
end
list_desc = <<-EOT.unindent
Lists VMs in the pool
EOT
rename_desc = <<-EOT.unindent
Renames the VM
EOT
@ -645,6 +641,52 @@ cmd=CommandParser::CmdParser.new(ARGV) do
end
end
# TODO: Write a more complete description:
# what is a snapshot (system snapshot)
# how to revert to a snapshot
snapshot_create_desc = <<-EOT.unindent
Creates a new VM snapshot
EOT
command :"snapshot-create", snapshot_create_desc, [:range,:vmid_list],
[:name, nil], :options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"snapshot created") do |o|
o.snapshot_create(args[1])
end
end
end
# TODO: Write a more complete description:
snapshot_revert_desc = <<-EOT.unindent
Reverts a VM to a saved snapshot
EOT
command :"snapshot-revert", snapshot_revert_desc, :vmid, :snapshot_id do
helper.perform_action(args[0],options,"snapshot reverted") do |o|
o.snapshot_revert(args[1].to_i)
end
end
# TODO: Write a more complete description:
snapshot_delete_desc = <<-EOT.unindent
Delets a snapshot of a VM
EOT
command :"snapshot-delete", snapshot_delete_desc, :vmid, :snapshot_id do
helper.perform_action(args[0],options,"snapshot deleted") do |o|
o.snapshot_delete(args[1].to_i)
end
end
list_desc = <<-EOT.unindent
Lists VMs in the pool
EOT
command :list, list_desc, [:filterflag, nil],
:options=>CLIHelper::OPTIONS+OpenNebulaHelper::OPTIONS+
[OpenNebulaHelper::DESCRIBE] do

View File

@ -1075,3 +1075,198 @@ int DispatchManager::detach(
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int DispatchManager::snapshot_create(
int vid,
string& name,
int& snap_id,
string& error_str)
{
ostringstream oss;
Nebula& nd = Nebula::instance();
VirtualMachineManager* vmm = nd.get_vmm();
VirtualMachine * vm = vmpool->get(vid, true);
if ( vm == 0 )
{
oss << "Could not create a new snapshot for VM " << vid
<< ", VM does not exist" ;
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
return -1;
}
if ( vm->get_state() != VirtualMachine::ACTIVE ||
vm->get_lcm_state() != VirtualMachine::RUNNING )
{
oss << "Could not create a new snapshot for VM " << vid
<< ", wrong state.";
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
vm->unlock();
return -1;
}
vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
vm->set_resched(false);
vm->new_snapshot(name, snap_id);
vmpool->update(vm);
vm->unlock();
vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int DispatchManager::snapshot_revert(
int vid,
int snap_id,
string& error_str)
{
ostringstream oss;
int rc;
Nebula& nd = Nebula::instance();
VirtualMachineManager* vmm = nd.get_vmm();
VirtualMachine * vm = vmpool->get(vid, true);
if ( vm == 0 )
{
oss << "Could not revert VM " << vid << " to snapshot " << snap_id
<< ", VM does not exist" ;
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
return -1;
}
if ( vm->get_state() != VirtualMachine::ACTIVE ||
vm->get_lcm_state() != VirtualMachine::RUNNING )
{
oss << "Could not revert VM " << vid << " to snapshot " << snap_id
<< ", wrong state.";
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
vm->unlock();
return -1;
}
rc = vm->set_active_snapshot(snap_id);
if ( rc == -1 )
{
oss << "Could not revert VM " << vid << " to snapshot " << snap_id
<< ", it does not exist.";
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
vm->unlock();
return -1;
}
vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
vm->set_resched(false);
vmpool->update(vm);
vm->unlock();
vmm->trigger(VirtualMachineManager::SNAPSHOT_REVERT,vid);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int DispatchManager::snapshot_delete(
int vid,
int snap_id,
string& error_str)
{
ostringstream oss;
int rc;
Nebula& nd = Nebula::instance();
VirtualMachineManager* vmm = nd.get_vmm();
VirtualMachine * vm = vmpool->get(vid, true);
if ( vm == 0 )
{
oss << "Could not delete snapshot " << snap_id << " for VM " << vid
<< ", VM does not exist" ;
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
return -1;
}
if ( vm->get_state() != VirtualMachine::ACTIVE ||
vm->get_lcm_state() != VirtualMachine::RUNNING )
{
oss << "Could not delete snapshot " << snap_id << " for VM " << vid
<< ", wrong state.";
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
vm->unlock();
return -1;
}
rc = vm->set_active_snapshot(snap_id);
if ( rc == -1 )
{
oss << "Could not delete snapshot " << snap_id << " for VM " << vid
<< ", it does not exist.";
error_str = oss.str();
NebulaLog::log("DiM", Log::ERROR, error_str);
vm->unlock();
return -1;
}
vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
vm->set_resched(false);
vmpool->update(vm);
vm->unlock();
vmm->trigger(VirtualMachineManager::SNAPSHOT_DELETE,vid);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -704,6 +704,9 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose)
}
vm->set_resched(false);
vm->delete_snapshots();
vmpool->update(vm);
vm->set_etime(the_time);
@ -735,6 +738,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose)
case VirtualMachine::SHUTDOWN_POWEROFF:
case VirtualMachine::CANCEL:
case VirtualMachine::HOTPLUG:
case VirtualMachine::HOTPLUG_SNAPSHOT:
vm->set_running_etime(the_time);
vmpool->update_history(vm);

View File

@ -153,6 +153,30 @@ void LifeCycleManager::trigger(Actions action, int _vid)
aname = "CLEANUP_FAILURE";
break;
case SNAPSHOT_CREATE_SUCCESS:
aname = "SNAPSHOT_CREATE_SUCCESS";
break;
case SNAPSHOT_CREATE_FAILURE:
aname = "SNAPSHOT_CREATE_FAILURE";
break;
case SNAPSHOT_REVERT_SUCCESS:
aname = "SNAPSHOT_REVERT_SUCCESS";
break;
case SNAPSHOT_REVERT_FAILURE:
aname = "SNAPSHOT_REVERT_FAILURE";
break;
case SNAPSHOT_DELETE_SUCCESS:
aname = "SNAPSHOT_DELETE_SUCCESS";
break;
case SNAPSHOT_DELETE_FAILURE:
aname = "SNAPSHOT_DELETE_FAILURE";
break;
case DEPLOY:
aname = "DEPLOY";
break;
@ -314,6 +338,30 @@ void LifeCycleManager::do_action(const string &action, void * arg)
{
cleanup_callback_action(vid);
}
else if (action == "SNAPSHOT_CREATE_SUCCESS")
{
snapshot_create_success(vid);
}
else if (action == "SNAPSHOT_CREATE_FAILURE")
{
snapshot_create_failure(vid);
}
else if (action == "SNAPSHOT_REVERT_SUCCESS")
{
snapshot_revert_success(vid);
}
else if (action == "SNAPSHOT_REVERT_FAILURE")
{
snapshot_revert_failure(vid);
}
else if (action == "SNAPSHOT_DELETE_SUCCESS")
{
snapshot_delete_success(vid);
}
else if (action == "SNAPSHOT_DELETE_FAILURE")
{
snapshot_delete_failure(vid);
}
else if (action == "DEPLOY")
{
deploy_action(vid);

View File

@ -45,6 +45,8 @@ void LifeCycleManager::save_success_action(int vid)
vm->set_state(VirtualMachine::PROLOG_MIGRATE);
vm->delete_snapshots();
vmpool->update(vm);
vm->set_previous_etime(the_time);
@ -81,6 +83,10 @@ void LifeCycleManager::save_success_action(int vid)
// SUSPENDED STATE
//----------------------------------------------------
vm->delete_snapshots();
vmpool->update(vm);
vm->set_running_etime(the_time);
vm->set_etime(the_time);
@ -107,6 +113,8 @@ void LifeCycleManager::save_success_action(int vid)
vm->set_state(VirtualMachine::EPILOG_STOP);
vm->delete_snapshots();
vmpool->update(vm);
vm->set_epilog_stime(the_time);
@ -272,6 +280,8 @@ void LifeCycleManager::deploy_success_action(int vid)
vm->set_state(VirtualMachine::RUNNING);
vm->delete_snapshots();
vmpool->update(vm);
vm->log("LCM", Log::INFO, "New VM state is RUNNING");
@ -464,6 +474,8 @@ void LifeCycleManager::shutdown_success_action(int vid)
vm->set_state(VirtualMachine::EPILOG);
vm->delete_snapshots();
vmpool->update(vm);
vm->set_epilog_stime(the_time);
@ -484,6 +496,10 @@ void LifeCycleManager::shutdown_success_action(int vid)
// POWEROFF STATE
//----------------------------------------------------
vm->delete_snapshots();
vmpool->update(vm);
vm->set_running_etime(the_time);
vm->set_etime(the_time);
@ -859,6 +875,8 @@ void LifeCycleManager::cancel_success_action(int vid)
vm->set_state(VirtualMachine::EPILOG);
vm->delete_snapshots();
vmpool->update(vm);
vm->set_reason(History::CANCEL);
@ -987,6 +1005,8 @@ void LifeCycleManager::monitor_suspend_action(int vid)
vm->set_resched(false);
vm->delete_snapshots();
vmpool->update(vm);
vm->set_running_etime(the_time);
@ -1073,6 +1093,8 @@ void LifeCycleManager::failure_action(VirtualMachine * vm)
vm->set_resched(false);
vm->delete_snapshots();
vmpool->update(vm);
vm->set_etime(the_time);
@ -1197,3 +1219,166 @@ void LifeCycleManager::detach_failure_action(int vid)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::snapshot_create_success(int vid)
{
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_SNAPSHOT )
{
vm->clear_active_snapshot();
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
}
else
{
vm->log("LCM",Log::ERROR,"snapshot_create_success, VM in a wrong state");
}
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::snapshot_create_failure(int vid)
{
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_SNAPSHOT )
{
vm->delete_active_snapshot();
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
}
else
{
vm->log("LCM",Log::ERROR,"snapshot_create_failure, VM in a wrong state");
}
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::snapshot_revert_success(int vid)
{
// TODO: snapshot list may be inconsistent with hypervisor info
// after a revert operation
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_SNAPSHOT )
{
vm->clear_active_snapshot();
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
}
else
{
vm->log("LCM",Log::ERROR,"snapshot_revert_success, VM in a wrong state");
}
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::snapshot_revert_failure(int vid)
{
// TODO: for now, it is the same code
snapshot_revert_success(vid);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::snapshot_delete_success(int vid)
{
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_SNAPSHOT )
{
vm->delete_active_snapshot();
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
}
else
{
vm->log("LCM",Log::ERROR,"snapshot_delete_success, VM in a wrong state");
}
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void LifeCycleManager::snapshot_delete_failure(int vid)
{
VirtualMachine * vm;
vm = vmpool->get(vid,true);
if ( vm == 0 )
{
return;
}
if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_SNAPSHOT )
{
vm->clear_active_snapshot();
vm->set_state(VirtualMachine::RUNNING);
vmpool->update(vm);
}
else
{
vm->log("LCM",Log::ERROR,"snapshot_delete_failure, VM in a wrong state");
}
vm->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -30,19 +30,22 @@ class VirtualMachineDriver < OpenNebulaDriver
# Virtual Machine Driver Protocol constants
ACTION = {
:deploy => "DEPLOY",
:shutdown => "SHUTDOWN",
:reboot => "REBOOT",
:reset => "RESET",
:cancel => "CANCEL",
:save => "SAVE",
:restore => "RESTORE",
:migrate => "MIGRATE",
:poll => "POLL",
:log => "LOG",
:attach_disk => "ATTACHDISK",
:detach_disk => "DETACHDISK",
:cleanup => "CLEANUP"
:deploy => "DEPLOY",
:shutdown => "SHUTDOWN",
:reboot => "REBOOT",
:reset => "RESET",
:cancel => "CANCEL",
:save => "SAVE",
:restore => "RESTORE",
:migrate => "MIGRATE",
:poll => "POLL",
:log => "LOG",
:attach_disk => "ATTACHDISK",
:detach_disk => "DETACHDISK",
:snapshot_create => "SNAPSHOTCREATE",
:snapshot_revert => "SNAPSHOTREVERT",
:snapshot_delete => "SNAPSHOTDELETE",
:cleanup => "CLEANUP"
}
POLL_ATTRIBUTE = {
@ -79,18 +82,24 @@ class VirtualMachineDriver < OpenNebulaDriver
@hosts = Array.new
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[:reset].to_sym, method("reset"))
register_action(ACTION[:cancel].to_sym, method("cancel"))
register_action(ACTION[:save].to_sym, method("save"))
register_action(ACTION[:restore].to_sym, method("restore"))
register_action(ACTION[:migrate].to_sym, method("migrate"))
register_action(ACTION[:poll].to_sym, method("poll"))
register_action(ACTION[:attach_disk].to_sym, method("attach_disk"))
register_action(ACTION[:detach_disk].to_sym, method("detach_disk"))
register_action(ACTION[:cleanup].to_sym, method("cleanup"))
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[:reset].to_sym, method("reset"))
register_action(ACTION[:cancel].to_sym, method("cancel"))
register_action(ACTION[:save].to_sym, method("save"))
register_action(ACTION[:restore].to_sym, method("restore"))
register_action(ACTION[:migrate].to_sym, method("migrate"))
register_action(ACTION[:poll].to_sym, method("poll"))
register_action(ACTION[:attach_disk].to_sym, method("attach_disk"))
register_action(ACTION[:detach_disk].to_sym, method("detach_disk"))
register_action(ACTION[:snapshot_create].to_sym,
method("snapshot_create"))
register_action(ACTION[:snapshot_revert].to_sym,
method("snapshot_revert"))
register_action(ACTION[:snapshot_delete].to_sym,
method("snapshot_delete"))
register_action(ACTION[:cleanup].to_sym, method("cleanup"))
end
# Decodes the encoded XML driver message received from the core
@ -170,6 +179,21 @@ class VirtualMachineDriver < OpenNebulaDriver
send_message(ACTION[:detach_disk],RESULT[:failure],id,error)
end
def snapshot_create(id, drv_message)
error = "Action not implemented by driver #{self.class}"
send_message(ACTION[:snapshot_create],RESULT[:failure],id,error)
end
def snapshot_revert(id, drv_message)
error = "Action not implemented by driver #{self.class}"
send_message(ACTION[:snapshot_revert],RESULT[:failure],id,error)
end
def snapshot_delete(id, drv_message)
error = "Action not implemented by driver #{self.class}"
send_message(ACTION[:snapshot_delete],RESULT[:failure],id,error)
end
def cleanup(id, drv_message)
error = "Action not implemented by driver #{self.class}"
send_message(ACTION[:cleanup],RESULT[:failure],id,error)

View File

@ -92,7 +92,8 @@ public class VirtualMachine extends PoolElement{
"BOOT_POWEROFF",
"BOOT_SUSPENDED",
"BOOT_STOPPED",
"CLEANUP_DELETE" };
"CLEANUP_DELETE",
"HOTPLUG_SNAPSHOT" };
private static final String[] SHORT_LCM_STATES =
{
@ -119,7 +120,8 @@ public class VirtualMachine extends PoolElement{
"boot",
"boot",
"boot",
"clea" };
"clea",
"snap" };
/**
* Creates a new VM representation.

View File

@ -38,7 +38,10 @@ module OpenNebula
:detach => "vm.detach",
:rename => "vm.rename",
:update => "vm.update",
:resize => "vm.resize"
:resize => "vm.resize",
:snapshotcreate => "vm.snapshotcreate",
:snapshotrevert => "vm.snapshotrevert",
:snapshotdelete => "vm.snapshotdelete"
}
VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
@ -47,7 +50,8 @@ module OpenNebula
LCM_STATE=%w{LCM_INIT PROLOG BOOT RUNNING MIGRATE SAVE_STOP SAVE_SUSPEND
SAVE_MIGRATE PROLOG_MIGRATE PROLOG_RESUME EPILOG_STOP EPILOG
SHUTDOWN CANCEL FAILURE CLEANUP_RESUBMIT UNKNOWN HOTPLUG SHUTDOWN_POWEROFF
BOOT_UNKNOWN BOOT_POWEROFF BOOT_SUSPENDED BOOT_STOPPED CLEANUP_DELETE}
BOOT_UNKNOWN BOOT_POWEROFF BOOT_SUSPENDED BOOT_STOPPED CLEANUP_DELETE
HOTPLUG_SNAPSHOT}
SHORT_VM_STATES={
"INIT" => "init",
@ -84,7 +88,8 @@ module OpenNebula
"BOOT_POWEROFF" => "boot",
"BOOT_SUSPENDED" => "boot",
"BOOT_STOPPED" => "boot",
"CLEANUP_DELETE" => "clea"
"CLEANUP_DELETE" => "clea",
"HOTPLUG_SNAPSHOT" => "snap"
}
MIGRATE_REASON=%w{NONE ERROR STOP_RESUME USER CANCEL}
@ -427,6 +432,39 @@ module OpenNebula
return call(VM_METHODS[:rename], @pe_id, name)
end
# Creates a new VM snapshot
#
# @param name [String] Name for the snapshot.
#
# @return [Integer, OpenNebula::Error] The new snaphost ID in case
# of success, Error otherwise
def snapshot_create(name="")
return Error.new('ID not defined') if !@pe_id
name ||= ""
return @client.call(VM_METHODS[:snapshotcreate], @pe_id, name)
end
# Reverts to a snapshot
#
# @param snap_id [Integer] Id of the snapshot
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def snapshot_revert(snap_id)
return call(VM_METHODS[:snapshotrevert], @pe_id, snap_id)
end
# Deletes a VM snapshot
#
# @param snap_id [Integer] Id of the snapshot
#
# @return [nil, OpenNebula::Error] nil in case of success, Error
# otherwise
def snapshot_delete(snap_id)
return call(VM_METHODS[:snapshotdelete], @pe_id, snap_id)
end
#######################################################################
# Helpers to get VirtualMachine information
#######################################################################

View File

@ -102,7 +102,8 @@ var oZones = {
"BOOT_POWEROFF",
"BOOT_SUSPENDED",
"BOOT_STOPPED",
"CLEANUP_DELETE"][value]);
"CLEANUP_DELETE",
"HOTPLUG_SNAPSHOT"][value]);
break;
case "IMAGE":
case "image":

View File

@ -255,6 +255,9 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr vm_attach(new VirtualMachineAttach());
xmlrpc_c::methodPtr vm_detach(new VirtualMachineDetach());
xmlrpc_c::methodPtr vm_resize(new VirtualMachineResize());
xmlrpc_c::methodPtr vm_snap_create(new VirtualMachineSnapshotCreate());
xmlrpc_c::methodPtr vm_snap_revert(new VirtualMachineSnapshotRevert());
xmlrpc_c::methodPtr vm_snap_delete(new VirtualMachineSnapshotDelete());
xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting());
xmlrpc_c::methodPtr vm_pool_monitoring(new VirtualMachinePoolMonitoring());
@ -399,6 +402,9 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.vm.rename", vm_rename);
RequestManagerRegistry.addMethod("one.vm.resize", vm_resize);
RequestManagerRegistry.addMethod("one.vm.update", vm_update);
RequestManagerRegistry.addMethod("one.vm.snapshotcreate", vm_snap_create);
RequestManagerRegistry.addMethod("one.vm.snapshotrevert", vm_snap_revert);
RequestManagerRegistry.addMethod("one.vm.snapshotdelete", vm_snap_delete);
RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
RequestManagerRegistry.addMethod("one.vmpool.accounting", vm_pool_acct);

View File

@ -1383,3 +1383,130 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
success_response(id, att);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineSnapshotCreate::request_execute(
xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
Nebula& nd = Nebula::instance();
DispatchManager * dm = nd.get_dm();
int rc;
int snap_id;
string error_str;
int id = xmlrpc_c::value_int(paramList.getInt(1));
string name = xmlrpc_c::value_string(paramList.getString(2));
// -------------------------------------------------------------------------
// Authorize the operation
// -------------------------------------------------------------------------
if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false )
{
return;
}
rc = dm->snapshot_create(id, name, snap_id, error_str);
if ( rc != 0 )
{
failure_response(ACTION,
request_error(error_str, ""),
att);
}
else
{
success_response(snap_id, att);
}
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineSnapshotRevert::request_execute(
xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
Nebula& nd = Nebula::instance();
DispatchManager * dm = nd.get_dm();
int rc;
string error_str;
int id = xmlrpc_c::value_int(paramList.getInt(1));
int snap_id = xmlrpc_c::value_int(paramList.getInt(2));
// -------------------------------------------------------------------------
// Authorize the operation
// -------------------------------------------------------------------------
if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false )
{
return;
}
rc = dm->snapshot_revert(id, snap_id, error_str);
if ( rc != 0 )
{
failure_response(ACTION,
request_error(error_str, ""),
att);
}
else
{
success_response(id, att);
}
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineSnapshotDelete::request_execute(
xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
Nebula& nd = Nebula::instance();
DispatchManager * dm = nd.get_dm();
int rc;
string error_str;
int id = xmlrpc_c::value_int(paramList.getInt(1));
int snap_id = xmlrpc_c::value_int(paramList.getInt(2));
// -------------------------------------------------------------------------
// Authorize the operation
// -------------------------------------------------------------------------
if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false )
{
return;
}
rc = dm->snapshot_delete(id, snap_id, error_str);
if ( rc != 0 )
{
failure_response(ACTION,
request_error(error_str, ""),
att);
}
else
{
success_response(id, att);
}
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -254,14 +254,28 @@ int VirtualMachineActionsPoolXML::action(
try
{
client->call( client->get_endpoint(), // serverUrl
if (action == "snapshot-create")
{
client->call( client->get_endpoint(), // serverUrl
"one.vm.snapshotcreate", // methodName
"sis", // arguments format
&result, // resultP
client->get_oneauth().c_str(), // session
vid, // VM ID
string("").c_str() // snapshot name
);
}
else
{
client->call( client->get_endpoint(), // serverUrl
"one.vm.action", // methodName
"ssi", // arguments format
&result, // resultP
client->get_oneauth().c_str(), // session
action.c_str(), // action
vid // VM ID
);
);
}
}
catch (exception const& e)
{

View File

@ -312,7 +312,8 @@ int VirtualMachineXML::parse_action_name(string& action_st)
&& action_st != "reboot"
&& action_st != "reset"
&& action_st != "poweroff"
&& action_st != "finalize")
&& action_st != "finalize"
&& action_st != "snapshot-create")
{
return -1;
}

View File

@ -110,7 +110,8 @@ var OpenNebula = {
"BOOT_POWEROFF",
"BOOT_SUSPENDED",
"BOOT_STOPPED",
"CLEANUP_DELETE"][value]);
"CLEANUP_DELETE",
"HOTPLUG_SNAPSHOT"][value]);
break;
case "IMAGE":
case "image":

View File

@ -50,7 +50,7 @@ var vm_graphs = [
];
var VNCstates=["RUNNING","SHUTDOWN","SHUTDOWN_POWEROFF","UNKNOWN","HOTPLUG","CANCEL","MIGRATE"];
var VNCstates=["RUNNING","SHUTDOWN","SHUTDOWN_POWEROFF","UNKNOWN","HOTPLUG","CANCEL","MIGRATE", "HOTPLUG_SNAPSHOT"];
//Permanent storage for last value of aggregated network usage
//Used to calculate bandwidth

View File

@ -1904,6 +1904,190 @@ void VirtualMachine::release_disk_images()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::new_snapshot(string& name, int& snap_id)
{
int num_snaps;
int id;
int max_id = -1;
vector<Attribute *> snaps;
VectorAttribute * snap;
num_snaps = obj_template->get("SNAPSHOT", snaps);
for(int i=0; i<num_snaps; i++)
{
snap = dynamic_cast<VectorAttribute * >(snaps[i]);
if ( snap == 0 )
{
continue;
}
snap->vector_value("SNAPSHOT_ID", id);
if (id > max_id)
{
max_id = id;
}
}
snap_id = max_id + 1;
if (name.empty())
{
ostringstream oss;
oss << "snapshot-" << snap_id;
name = oss.str();
}
snap = new VectorAttribute("SNAPSHOT");
snap->replace("SNAPSHOT_ID", snap_id);
snap->replace("NAME", name);
snap->replace("TIME", (int)time(0));
snap->replace("HYPERVISOR_ID", "");
snap->replace("ACTIVE", "YES");
obj_template->set(snap);
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::set_active_snapshot(int snap_id)
{
int num_snaps;
int s_id;
vector<Attribute *> snaps;
VectorAttribute * snap;
num_snaps = obj_template->get("SNAPSHOT", snaps);
for(int i=0; i<num_snaps; i++)
{
snap = dynamic_cast<VectorAttribute * >(snaps[i]);
if ( snap == 0 )
{
continue;
}
snap->vector_value("SNAPSHOT_ID", s_id);
if ( s_id == snap_id )
{
snap->replace("ACTIVE", "YES");
return 0;
}
}
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::update_snapshot_id(string& hypervisor_id)
{
int num_snaps;
vector<Attribute *> snaps;
VectorAttribute * snap;
num_snaps = obj_template->get("SNAPSHOT", snaps);
for(int i=0; i<num_snaps; i++)
{
snap = dynamic_cast<VectorAttribute * >(snaps[i]);
if ( snap == 0 )
{
continue;
}
if ( snap->vector_value("ACTIVE") == "YES" )
{
snap->replace("HYPERVISOR_ID", hypervisor_id);
break;
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::clear_active_snapshot()
{
int num_snaps;
vector<Attribute *> snaps;
VectorAttribute * snap;
num_snaps = obj_template->get("SNAPSHOT", snaps);
for(int i=0; i<num_snaps; i++)
{
snap = dynamic_cast<VectorAttribute * >(snaps[i]);
if ( snap == 0 )
{
continue;
}
if ( snap->vector_value("ACTIVE") == "YES" )
{
snap->remove("ACTIVE");
return;
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::delete_active_snapshot()
{
vector<Attribute *> snaps;
VectorAttribute * snap;
int num_snaps = obj_template->get("SNAPSHOT", snaps);
for(int i=0; i<num_snaps; i++)
{
snap = dynamic_cast<VectorAttribute * >(snaps[i]);
if ( snap == 0 )
{
continue;
}
if ( snap->vector_value("ACTIVE") == "YES" )
{
if (obj_template->remove(snap) != 0)
{
delete snap;
}
return;
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachine::delete_snapshots()
{
obj_template->erase("SNAPSHOT");
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachine::get_network_leases(string& estr)
{
int num_nics, rc;

View File

@ -183,6 +183,17 @@ void VirtualMachineManager::trigger(Actions action, int _vid)
aname = "DETACH";
break;
case SNAPSHOT_CREATE:
aname = "SNAPSHOT_CREATE";
break;
case SNAPSHOT_REVERT:
aname = "SNAPSHOT_REVERT";
break;
case SNAPSHOT_DELETE:
aname = "SNAPSHOT_DELETE";
break;
default:
delete vid;
return;
@ -279,6 +290,18 @@ void VirtualMachineManager::do_action(const string &action, void * arg)
{
detach_action(vid);
}
else if (action == "SNAPSHOT_CREATE")
{
snapshot_create_action(vid);
}
else if (action == "SNAPSHOT_REVERT")
{
snapshot_revert_action(vid);
}
else if (action == "SNAPSHOT_DELETE")
{
snapshot_delete_action(vid);
}
else if (action == ACTION_TIMER)
{
timer_action();
@ -1761,6 +1784,237 @@ error_common:
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManager::snapshot_create_action(int vid)
{
VirtualMachine * vm;
const VirtualMachineManagerDriver * vmd;
ostringstream os;
string vm_tmpl;
string* drv_msg;
// 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;
}
drv_msg = format_message(
vm->get_hostname(),
vm->get_vnm_mad(),
"",
"",
vm->get_deploy_id(),
"",
"",
"",
"",
"",
vm->to_xml(vm_tmpl));
vmd->snapshot_create(vid, *drv_msg);
delete drv_msg;
vm->unlock();
return;
error_history:
os.str("");
os << "snapshot_create_action, VM has no history";
goto error_common;
error_driver:
os.str("");
os << "snapshot_create_action, error getting driver " << vm->get_vmm_mad();
goto error_common;
error_common:
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();
lcm->trigger(LifeCycleManager::SNAPSHOT_CREATE_FAILURE, vid);
vm->log("VMM", Log::ERROR, os);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManager::snapshot_revert_action(int vid)
{
VirtualMachine * vm;
const VirtualMachineManagerDriver * vmd;
ostringstream os;
string vm_tmpl;
string* drv_msg;
// 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;
}
drv_msg = format_message(
vm->get_hostname(),
vm->get_vnm_mad(),
"",
"",
vm->get_deploy_id(),
"",
"",
"",
"",
"",
vm->to_xml(vm_tmpl));
vmd->snapshot_revert(vid, *drv_msg);
delete drv_msg;
vm->unlock();
return;
error_history:
os.str("");
os << "snapshot_revert_action, VM has no history";
goto error_common;
error_driver:
os.str("");
os << "snapshot_revert_action, error getting driver " << vm->get_vmm_mad();
goto error_common;
error_common:
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();
lcm->trigger(LifeCycleManager::SNAPSHOT_REVERT_FAILURE, vid);
vm->log("VMM", Log::ERROR, os);
vm->unlock();
return;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineManager::snapshot_delete_action(int vid)
{
VirtualMachine * vm;
const VirtualMachineManagerDriver * vmd;
ostringstream os;
string vm_tmpl;
string* drv_msg;
// 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;
}
drv_msg = format_message(
vm->get_hostname(),
vm->get_vnm_mad(),
"",
"",
vm->get_deploy_id(),
"",
"",
"",
"",
"",
vm->to_xml(vm_tmpl));
vmd->snapshot_delete(vid, *drv_msg);
delete drv_msg;
vm->unlock();
return;
error_history:
os.str("");
os << "snapshot_delete_action, VM has no history";
goto error_common;
error_driver:
os.str("");
os << "snapshot_delete_action, error getting driver " << vm->get_vmm_mad();
goto error_common;
error_common:
Nebula &ne = Nebula::instance();
LifeCycleManager * lcm = ne.get_lcm();
lcm->trigger(LifeCycleManager::SNAPSHOT_DELETE_FAILURE, vid);
vm->log("VMM", Log::ERROR, os);
vm->unlock();
return;
}
/* ************************************************************************** */
/* MAD Loading */
/* ************************************************************************** */

View File

@ -364,7 +364,7 @@ void VirtualMachineManagerDriver::protocol(
LifeCycleManager *lcm = ne.get_lcm();
if ( result == "SUCCESS" )
{
{
vm->log("VMM", Log::INFO, "VM Disk successfully attached.");
lcm->trigger(LifeCycleManager::ATTACH_SUCCESS, id);
@ -396,6 +396,71 @@ void VirtualMachineManagerDriver::protocol(
lcm->trigger(LifeCycleManager::DETACH_FAILURE, id);
}
}
else if ( action == "SNAPSHOTCREATE" )
{
Nebula &ne = Nebula::instance();
LifeCycleManager *lcm = ne.get_lcm();
if ( result == "SUCCESS" )
{
string hypervisor_id;
is >> hypervisor_id;
vm->update_snapshot_id(hypervisor_id);
vmpool->update(vm);
vm->log("VMM", Log::INFO, "VM Snapshot successfully created.");
lcm->trigger(LifeCycleManager::SNAPSHOT_CREATE_SUCCESS, id);
}
else
{
log_error(vm, os, is, "Error creating new VM Snapshot");
vmpool->update(vm);
lcm->trigger(LifeCycleManager::SNAPSHOT_CREATE_FAILURE, id);
}
}
else if ( action == "SNAPSHOTREVERT" )
{
Nebula &ne = Nebula::instance();
LifeCycleManager *lcm = ne.get_lcm();
if ( result == "SUCCESS" )
{
vm->log("VMM",Log::INFO,"VM Snapshot successfully reverted.");
lcm->trigger(LifeCycleManager::SNAPSHOT_REVERT_SUCCESS, id);
}
else
{
log_error(vm,os,is,"Error reverting VM Snapshot");
vmpool->update(vm);
lcm->trigger(LifeCycleManager::SNAPSHOT_REVERT_FAILURE, id);
}
}
else if ( action == "SNAPSHOTDELETE" )
{
Nebula &ne = Nebula::instance();
LifeCycleManager *lcm = ne.get_lcm();
if ( result == "SUCCESS" )
{
vm->log("VMM",Log::INFO,"VM Snapshot successfully deleted.");
lcm->trigger(LifeCycleManager::SNAPSHOT_DELETE_SUCCESS, id);
}
else
{
log_error(vm,os,is,"Error deleting VM Snapshot");
vmpool->update(vm);
lcm->trigger(LifeCycleManager::SNAPSHOT_DELETE_FAILURE, id);
}
}
else if ( action == "CLEANUP" )
{
Nebula &ne = Nebula::instance();

View File

@ -608,6 +608,66 @@ class ExecDriver < VirtualMachineDriver
action.run(steps)
end
#
# SNAPSHOTCREATE action, creates a new system snapshot
#
def snapshot_create(id, drv_message)
action = ACTION[:snapshot_create]
xml_data = decode(drv_message)
host = xml_data.elements['HOST'].text
deploy_id = xml_data.elements['DEPLOY_ID'].text
snap_id_xpath = "VM/TEMPLATE/SNAPSHOT[ACTIVE='YES']/SNAPSHOT_ID"
snap_id = xml_data.elements[snap_id_xpath].text.to_i
do_action("#{deploy_id} #{snap_id}",
id,
host,
ACTION[:snapshot_create],
:script_name => "snapshot_create")
end
#
# SNAPSHOTREVERT action, reverts to a system snapshot
#
def snapshot_revert(id, drv_message)
action = ACTION[:snapshot_revert]
xml_data = decode(drv_message)
host = xml_data.elements['HOST'].text
deploy_id = xml_data.elements['DEPLOY_ID'].text
snap_id_xpath = "VM/TEMPLATE/SNAPSHOT[ACTIVE='YES']/HYPERVISOR_ID"
snapshot_name = xml_data.elements[snap_id_xpath].text
do_action("#{deploy_id} #{snapshot_name}",
id,
host,
ACTION[:snapshot_revert],
:script_name => "snapshot_revert")
end
#
# SNAPSHOTDELETE action, deletes a system snapshot
#
def snapshot_delete(id, drv_message)
action = ACTION[:snapshot_delete]
xml_data = decode(drv_message)
host = xml_data.elements['HOST'].text
deploy_id = xml_data.elements['DEPLOY_ID'].text
snap_id_xpath = "VM/TEMPLATE/SNAPSHOT[ACTIVE='YES']/HYPERVISOR_ID"
snapshot_name = xml_data.elements[snap_id_xpath].text
do_action("#{deploy_id} #{snapshot_name}",
id,
host,
ACTION[:snapshot_delete],
:script_name => "snapshot_delete")
end
#
# CLEANUP action, frees resources allocated in a host: VM and disk images
#

View File

@ -22,4 +22,8 @@ else
MAD_LOCATION=$ONE_LOCATION/lib/mads
fi
exec $MAD_LOCATION/one_vmm_exec -l deploy,shutdown,reboot,cancel,save,restore,migrate,poll,pre,post,clean $*
LOCAL_ACTIONS="deploy,shutdown,reboot,cancel,save,restore,migrate,poll,pre"
LOCAL_ACTIONS="${LOCAL_ACTIONS},post,clean"
LOCAL_ACTIONS="${LOCAL_ACTIONS},snapshotcreate,snapshotrevert,snapshotdelete"
exec $MAD_LOCATION/one_vmm_exec -l $LOCAL_ACTIONS $*

View File

@ -0,0 +1,34 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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
DOMAIN="$1"
SNAP_ID="$2"
data=`virsh --connect $LIBVIRT_URI snapshot-create-as $DOMAIN`
if [ "$?" = "0" ]; then
echo "$data" | awk '{print $3}'
else
error_message "Could not create snapshot $NAME for domain $DOMAIN."
exit -1
fi
exit 0

View File

@ -0,0 +1,29 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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
DOMAIN="$1"
NAME="$2"
exec_and_log \
"virsh --connect $LIBVIRT_URI snapshot-delete $DOMAIN $NAME" \
"Could not delete snapshot $NAME for domain $DOMAIN."
exit 0

View File

@ -0,0 +1,29 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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
DOMAIN="$1"
NAME="$2"
exec_and_log \
"virsh --connect $LIBVIRT_URI snapshot-revert --force $DOMAIN $NAME" \
"Could not revert to snapshot $NAME for domain $DOMAIN."
exit 0

View File

@ -0,0 +1,40 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2010-2013, C12G Labs S.L #
# #
# 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. #
# ---------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vmware_driver'
deploy_id = ARGV[0]
host = ARGV[3]
vmware_drv = VMwareDriver.new(host)
hypervisor_id = vmware_drv.snapshot_create(deploy_id)
puts hypervisor_id
exit 0

View File

@ -0,0 +1,38 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2010-2013, C12G Labs S.L #
# #
# 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. #
# ---------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vmware_driver'
deploy_id = ARGV[0]
snapshot_id = ARGV[1]
host = ARGV[3]
vmware_drv = VMwareDriver.new(host)
vmware_drv.snapshot_delete(deploy_id, snapshot_id)

View File

@ -0,0 +1,38 @@
#!/usr/bin/env ruby
# ---------------------------------------------------------------------------- #
# Copyright 2010-2013, C12G Labs S.L #
# #
# 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. #
# ---------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION)
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION)
end
$: << RUBY_LIB_LOCATION
$: << File.dirname(__FILE__)
require 'vmware_driver'
deploy_id = ARGV[0]
snapshot_id = ARGV[1]
host = ARGV[3]
vmware_drv = VMwareDriver.new(host)
vmware_drv.snapshot_revert(deploy_id, snapshot_id)

View File

@ -262,6 +262,42 @@ class VMwareDriver
undefine_domain(deploy_id)
end
# ------------------------------------------------------------------------ #
# Creates a new system snapshot #
# ------------------------------------------------------------------------ #
def snapshot_create(deploy_id)
rc, info = do_action(
"virsh -c #{@uri} snapshot-create-as #{deploy_id}")
exit info if rc == false
hypervisor_id = info.split[2]
return hypervisor_id
end
# ------------------------------------------------------------------------ #
# Delete a system snapshot #
# ------------------------------------------------------------------------ #
def snapshot_delete(deploy_id, snapshot_id)
rc, info = do_action(
"virsh -c #{@uri} snapshot-delete #{deploy_id} #{snapshot_id}")
exit info if rc == false
end
# ------------------------------------------------------------------------ #
# Revert to a system snapshot #
# ------------------------------------------------------------------------ #
def snapshot_revert(deploy_id, snapshot_id)
action = "virsh -c #{@uri} snapshot-revert " <<
"--force #{deploy_id} #{snapshot_id}"
rc, info = do_action(action)
exit info if rc == false
end
# ######################################################################## #
# DRIVER HELPER FUNCTIONS #
# ######################################################################## #

View File

@ -0,0 +1,21 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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)/../../scripts_common.sh
log_error "Snapshotting is not yet supported for Xen."
exit 1

View File

@ -0,0 +1,22 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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)/../../scripts_common.sh
log_error "Snapshotting is not yet supported for Xen."
exit 1

View File

@ -0,0 +1,22 @@
#!/bin/bash
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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)/../../scripts_common.sh
log_error "Snapshotting is not yet supported for Xen."
exit 1