mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-18 06:03:39 +03:00
Feature #1224: New method one.vm.snapshotcreate
This commit is contained in:
parent
ae5561c27e
commit
08399c5732
@ -276,6 +276,20 @@ public:
|
||||
int disk_id,
|
||||
string& error_str);
|
||||
|
||||
/**
|
||||
* Starts the snapshot create action
|
||||
*
|
||||
* @param vid VirtualMachine identification
|
||||
* @param name Name for the new snapshot
|
||||
* @param error_str Error reason, if any
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int snapshot_create(
|
||||
int vid,
|
||||
string& name,
|
||||
string& error_str);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Thread id for the Dispatch Manager
|
||||
|
@ -64,6 +64,8 @@ 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 */
|
||||
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 +191,10 @@ private:
|
||||
|
||||
void cleanup_callback_action(int vid);
|
||||
|
||||
void snapshot_create_success(int vid);
|
||||
|
||||
void snapshot_create_failure(int vid);
|
||||
|
||||
void deploy_action(int vid);
|
||||
|
||||
void suspend_action(int vid);
|
||||
|
@ -217,6 +217,23 @@ public:
|
||||
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);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -924,6 +924,38 @@ public:
|
||||
*/
|
||||
int detach_failure();
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Snapshot related functions
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
int new_snapshot(string& name);
|
||||
|
||||
/**
|
||||
* Returns the snapshot with an active operation
|
||||
*
|
||||
* @return the snapshot with an active operation, or 0
|
||||
*/
|
||||
VectorAttribute* get_active_snapshot();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
private:
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -61,7 +61,8 @@ public:
|
||||
DRIVER_CANCEL,
|
||||
FINALIZE,
|
||||
ATTACH,
|
||||
DETACH
|
||||
DETACH,
|
||||
SNAPSHOT_CREATE
|
||||
};
|
||||
|
||||
/**
|
||||
@ -324,6 +325,12 @@ private:
|
||||
void attach_action(
|
||||
int vid);
|
||||
|
||||
/**
|
||||
* Creates a new system snapshot
|
||||
* @param vid the id of the VM.
|
||||
*/
|
||||
void snapshot_create_action(int vid);
|
||||
|
||||
/**
|
||||
* Detaches a disk from a VM. The VM must have a disk with the
|
||||
* attribute ATTACH = YES
|
||||
|
@ -284,6 +284,19 @@ 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);
|
||||
}
|
||||
|
||||
void write_drv(const char * aname, const int oid, const string& msg) const
|
||||
{
|
||||
ostringstream os;
|
||||
|
@ -1075,3 +1075,61 @@ int DispatchManager::detach(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DispatchManager::snapshot_create(
|
||||
int vid,
|
||||
string& name,
|
||||
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);
|
||||
|
||||
vm->set_resched(false);
|
||||
|
||||
vm->new_snapshot(name);
|
||||
|
||||
vmpool->update(vm);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -153,6 +153,14 @@ 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 DEPLOY:
|
||||
aname = "DEPLOY";
|
||||
break;
|
||||
@ -314,6 +322,14 @@ 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 == "DEPLOY")
|
||||
{
|
||||
deploy_action(vid);
|
||||
|
@ -1197,3 +1197,63 @@ 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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -254,6 +254,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vm_monitoring(new VirtualMachineMonitoring());
|
||||
xmlrpc_c::methodPtr vm_attach(new VirtualMachineAttach());
|
||||
xmlrpc_c::methodPtr vm_detach(new VirtualMachineDetach());
|
||||
xmlrpc_c::methodPtr vm_snap_create(new VirtualMachineSnapshotCreate());
|
||||
xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting());
|
||||
xmlrpc_c::methodPtr vm_pool_monitoring(new VirtualMachinePoolMonitoring());
|
||||
|
||||
@ -397,6 +398,7 @@ void RequestManager::register_xml_methods()
|
||||
RequestManagerRegistry.addMethod("one.vm.detach", vm_detach);
|
||||
RequestManagerRegistry.addMethod("one.vm.rename", vm_rename);
|
||||
RequestManagerRegistry.addMethod("one.vm.update", vm_update);
|
||||
RequestManagerRegistry.addMethod("one.vm.snapshotcreate", vm_snap_create);
|
||||
|
||||
RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
|
||||
RequestManagerRegistry.addMethod("one.vmpool.accounting", vm_pool_acct);
|
||||
|
@ -1054,5 +1054,47 @@ void VirtualMachineDetach::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineSnapshotCreate::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));
|
||||
string str = 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, str, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
failure_response(ACTION,
|
||||
request_error(error_str, ""),
|
||||
att);
|
||||
}
|
||||
else
|
||||
{
|
||||
success_response(id, att);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -1803,6 +1803,153 @@ void VirtualMachine::release_disk_images()
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::new_snapshot(string& name)
|
||||
{
|
||||
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 = new VectorAttribute("SNAPSHOT");
|
||||
snap->replace("SNAPSHOT_ID", max_id+1);
|
||||
snap->replace("NAME", name);
|
||||
snap->replace("TIME", (int)time(0));
|
||||
snap->replace("HYPERVISOR_ID", "");
|
||||
|
||||
snap->replace("ACTIVE", "YES");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
VectorAttribute* VirtualMachine::get_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" )
|
||||
{
|
||||
return snap;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachine::update_snapshot_id(string& hypervisor_id)
|
||||
{
|
||||
VectorAttribute* snap;
|
||||
|
||||
snap = get_active_snapshot();
|
||||
|
||||
if (snap == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
snap->replace("HYPERVISOR_ID", hypervisor_id);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::get_network_leases(string& estr)
|
||||
{
|
||||
int num_nics, rc;
|
||||
|
@ -183,6 +183,10 @@ void VirtualMachineManager::trigger(Actions action, int _vid)
|
||||
aname = "DETACH";
|
||||
break;
|
||||
|
||||
case SNAPSHOT_CREATE:
|
||||
aname = "SNAPSHOT_CREATE";
|
||||
break;
|
||||
|
||||
default:
|
||||
delete vid;
|
||||
return;
|
||||
@ -279,6 +283,10 @@ void VirtualMachineManager::do_action(const string &action, void * arg)
|
||||
{
|
||||
detach_action(vid);
|
||||
}
|
||||
else if (action == "SNAPSHOT_CREATE")
|
||||
{
|
||||
snapshot_create_action(vid);
|
||||
}
|
||||
else if (action == ACTION_TIMER)
|
||||
{
|
||||
timer_action();
|
||||
@ -1761,6 +1769,83 @@ 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;
|
||||
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* MAD Loading */
|
||||
/* ************************************************************************** */
|
||||
|
@ -370,6 +370,33 @@ 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 == "CLEANUP" )
|
||||
{
|
||||
Nebula &ne = Nebula::instance();
|
||||
|
Loading…
x
Reference in New Issue
Block a user