mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-11 04:58:16 +03:00
feature #3782: Create and Revert operations for Disk Snapshots. Core and
OCA levels
This commit is contained in:
parent
676bfcc1db
commit
98f76cf3fe
@ -363,6 +363,39 @@ public:
|
||||
int snap_id,
|
||||
string& error_str);
|
||||
|
||||
/**
|
||||
* Starts the disk snapshot create action
|
||||
*
|
||||
* @param vid VirtualMachine identification
|
||||
* @param did DISK identification
|
||||
* @param tag Description 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 disk_snapshot_create(
|
||||
int vid,
|
||||
int did,
|
||||
const string& tag,
|
||||
int& snap_id,
|
||||
string& error_str);
|
||||
|
||||
/**
|
||||
* Reverts the disk state to a previous snapshot
|
||||
*
|
||||
* @param vid VirtualMachine identification
|
||||
* @param did DISK identification
|
||||
* @param snap_id Snapshot to be restored
|
||||
* @param error_str Error reason, if any
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int disk_snapshot_revert(
|
||||
int vid,
|
||||
int did,
|
||||
int snap_id,
|
||||
string& error_str);
|
||||
private:
|
||||
/**
|
||||
* Thread id for the Dispatch Manager
|
||||
|
@ -405,4 +405,35 @@ public:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class VirtualMachineDiskSnapshotCreate: public RequestManagerVirtualMachine
|
||||
{
|
||||
public:
|
||||
VirtualMachineDiskSnapshotCreate():
|
||||
RequestManagerVirtualMachine("VirtualMachineDiskSnapshotCreate",
|
||||
"Creates a new virtual machine disk snapshot",
|
||||
"A:siis"){};
|
||||
|
||||
~VirtualMachineDiskSnapshotCreate(){};
|
||||
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class VirtualMachineDiskSnapshotRevert: public RequestManagerVirtualMachine
|
||||
{
|
||||
public:
|
||||
VirtualMachineDiskSnapshotRevert():
|
||||
RequestManagerVirtualMachine("VirtualMachineDiskSnapshotRevert",
|
||||
"Reverts disk state to a snapshot",
|
||||
"A:siii"){};
|
||||
|
||||
~VirtualMachineDiskSnapshotRevert(){};
|
||||
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -14,8 +14,8 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SNAPSHOT_POOL_H_
|
||||
#define SNAPSHOT_POOL_H_
|
||||
#ifndef SNAPSHOTS_H_
|
||||
#define SNAPSHOTS_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@ -30,8 +30,18 @@ using namespace std;
|
||||
class VectorAttribute;
|
||||
|
||||
/**
|
||||
* This class represents the List of Snapshots associated to an image or Virtual
|
||||
* Machine Disk
|
||||
* This class represents a list of Snapshots associated to an image or Virtual
|
||||
* Machine Disk. The list is in the form:
|
||||
* <SNAPSHOTS>
|
||||
* <DISK_ID>: of the disk the snapshots are taken from (the initial backing)
|
||||
* <ACTIVE>: the current snapshot in use by the VM. 0 for the original DISK
|
||||
* <SNAPSHOT>
|
||||
* <ID>
|
||||
* <TAG>: Description
|
||||
* <DATE>: the snapshot was taken
|
||||
* <PARENT_ID>: backing for this snapshot, 0 for the original image
|
||||
* <PARENT>: Opaque (driver specific) string representing the parent
|
||||
* <SOURCE>: Opaque (driver specific) string representing the snapshot
|
||||
*/
|
||||
class Snapshots
|
||||
{
|
||||
@ -52,15 +62,41 @@ public:
|
||||
*/
|
||||
int from_xml_node(const xmlNodePtr node);
|
||||
|
||||
int create_snapshot(unsigned int p_id, const string& tag, string& error);
|
||||
/**
|
||||
* XML Representation of the Snapshots
|
||||
*/
|
||||
string& to_xml(string& xml) const
|
||||
{
|
||||
return snapshot_template.to_xml(xml);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new (empty) snapshot of the active disk
|
||||
* @param src source of disk image (inital backing file)
|
||||
* @param tag description of this snapshot (optional)
|
||||
* @return id of the new snapshot
|
||||
*/
|
||||
int create_snapshot(const string& src, const string& tag);
|
||||
|
||||
/**
|
||||
* Removes the snapshot from the list
|
||||
* @param id of the snapshot
|
||||
*/
|
||||
int delete_snapshot(unsigned int id);
|
||||
|
||||
/**
|
||||
* Set the given snapshot as active. Updates the values of the current
|
||||
* snapshot
|
||||
*/
|
||||
int active_snapshot(unsigned int id);
|
||||
int active_snapshot(unsigned int id, string& error);
|
||||
|
||||
/**
|
||||
* Return the disk_id of the snapshot list
|
||||
*/
|
||||
int get_disk_id()
|
||||
{
|
||||
return disk_id;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -71,15 +107,31 @@ private:
|
||||
*/
|
||||
VectorAttribute * get_snapshot(unsigned int id);
|
||||
|
||||
/**
|
||||
* Text representation of the snapshot pool. To be stored as part of the
|
||||
* VM or Image Templates
|
||||
*/
|
||||
Template snapshot_template;
|
||||
|
||||
/**
|
||||
* Next id
|
||||
*/
|
||||
unsigned int next_snapshot;
|
||||
|
||||
/**
|
||||
* Id of the active (current) snapshot, 0 represents the base image
|
||||
*/
|
||||
unsigned int active;
|
||||
|
||||
/**
|
||||
* Id of the disk associated with this snapshot list
|
||||
*/
|
||||
unsigned int disk_id;
|
||||
|
||||
/**
|
||||
* Snapshot pointer map
|
||||
*/
|
||||
map<unsigned int, VectorAttribute *> snapshot_pool;
|
||||
|
||||
unsigned int active;
|
||||
};
|
||||
|
||||
#endif /*SNAPSHOT_H_*/
|
||||
#endif /*SNAPSHOTS_H_*/
|
@ -32,6 +32,7 @@
|
||||
using namespace std;
|
||||
|
||||
class AuthRequest;
|
||||
class Snapshots;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -1495,6 +1496,28 @@ public:
|
||||
*/
|
||||
int set_attach_nic(int nic_id);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Snapshot related functions
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a new snapshot of the given disk
|
||||
* @param disk_id of the disk
|
||||
* @param tag a description for this snapshot
|
||||
* @param error if any
|
||||
* @return the id of the new snapshot or -1 if error
|
||||
*/
|
||||
int new_disk_snapshot(int disk_id, const string& tag, string& error);
|
||||
|
||||
/**
|
||||
* Sets the snap_id as active, the VM will boot from it next time
|
||||
* @param disk_id of the disk
|
||||
* @param snap_id of the snapshot. It can be 0 to revert to the original
|
||||
* disk
|
||||
* @param error if any
|
||||
* @return -1 if error
|
||||
*/
|
||||
int revert_disk_snapshot(int disk_id, int snap_id, string& error);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Snapshot related functions
|
||||
@ -1651,6 +1674,11 @@ private:
|
||||
*/
|
||||
vector<History *> history_records;
|
||||
|
||||
/**
|
||||
* Snapshots for each disk
|
||||
*/
|
||||
map<int, Snapshots *> snapshots;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Logging & Dirs
|
||||
// -------------------------------------------------------------------------
|
||||
@ -1797,12 +1825,12 @@ private:
|
||||
*/
|
||||
int parse_defaults(string& error_str);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Known attributes for network contextualization rendered as:
|
||||
* ETH_<nicid>_<context[0]> = $NETWORK[context[1], vnet_name]
|
||||
*
|
||||
* The context[1] values in the map are searched in the NIC and
|
||||
* if not found in the AR and VNET. They can be also set in the
|
||||
* The context[1] values in the map are searched in the NIC and
|
||||
* if not found in the AR and VNET. They can be also set in the
|
||||
* CONTEXT section it self using full name (ETH_).
|
||||
*
|
||||
* IPv4 context variables:
|
||||
@ -1924,6 +1952,13 @@ private:
|
||||
*/
|
||||
int get_disk_images(string &error_str);
|
||||
|
||||
/**
|
||||
* Return the VectorAttribute representation of a disk
|
||||
* @param disk_id of the disk
|
||||
* @return pointer to the VectorAttribute
|
||||
*/
|
||||
VectorAttribute* get_disk(int disk_id);
|
||||
|
||||
protected:
|
||||
|
||||
//**************************************************************************
|
||||
@ -1998,11 +2033,6 @@ protected:
|
||||
return -1;
|
||||
}
|
||||
|
||||
// *************************************************************************
|
||||
// Helpers
|
||||
// *************************************************************************
|
||||
|
||||
VectorAttribute* get_disk(int disk_id);
|
||||
};
|
||||
|
||||
#endif /*VIRTUAL_MACHINE_H_*/
|
||||
|
@ -785,6 +785,34 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
end
|
||||
end
|
||||
|
||||
disk_snapshot_create_desc = <<-EOT.unindent
|
||||
Takes a new snapshot of the given disk. This operation needs support
|
||||
from the Datastore drivers: QCOW2 or Ceph.
|
||||
|
||||
States: POWEROFF
|
||||
EOT
|
||||
|
||||
command :"disk-snapshot-create", disk_snapshot_create_desc,
|
||||
:vmid, :diskid, :tag do
|
||||
helper.perform_action(args[0],options,"disk snapshot created") do |o|
|
||||
o.disk_snapshot_create(args[1].to_i, args[2])
|
||||
end
|
||||
end
|
||||
|
||||
disk_snapshot_revert_desc = <<-EOT.unindent
|
||||
Reverts disk state to a previously taken snapshot. To revert
|
||||
disk state to the base disk image use 0 as snapshot id
|
||||
|
||||
States: POWEROFF
|
||||
EOT
|
||||
|
||||
command :"disk-snapshot-revert", disk_snapshot_revert_desc,
|
||||
:vmid, :diskid, :snapshot_id do
|
||||
helper.perform_action(args[0],options,"disk snapshot reverted") do |o|
|
||||
o.disk_snapshot_revert(args[1].to_i, args[2].to_i)
|
||||
end
|
||||
end
|
||||
|
||||
list_desc = <<-EOT.unindent
|
||||
Lists VMs in the pool
|
||||
EOT
|
||||
|
@ -1146,10 +1146,10 @@ int DispatchManager::detach(
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DispatchManager::snapshot_create(
|
||||
int vid,
|
||||
string& name,
|
||||
int& snap_id,
|
||||
string& error_str)
|
||||
int vid,
|
||||
string& name,
|
||||
int& snap_id,
|
||||
string& error_str)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
@ -1606,3 +1606,117 @@ int DispatchManager::detach_nic(
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DispatchManager::disk_snapshot_create(
|
||||
int vid,
|
||||
int did,
|
||||
const string& tag,
|
||||
int& snap_id,
|
||||
string& error_str)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
VirtualMachine * vm = vmpool->get(vid, true);
|
||||
|
||||
if ( vm == 0 )
|
||||
{
|
||||
oss << "Could not create a new disk 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::POWEROFF ||
|
||||
vm->get_lcm_state() != VirtualMachine::LCM_INIT )
|
||||
{
|
||||
oss << "Could not create a new snapshot for VM " << vid
|
||||
<< ", wrong state " << vm->state_str() << ".";
|
||||
error_str = oss.str();
|
||||
|
||||
NebulaLog::log("DiM", Log::ERROR, error_str);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//TODO set state (reuse HOTPLUG_SNAPSHOT?)
|
||||
//vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
|
||||
|
||||
snap_id = vm->new_disk_snapshot(did, tag, error_str);
|
||||
|
||||
if (snap_id == -1)
|
||||
{
|
||||
vm->unlock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
vmpool->update(vm);
|
||||
|
||||
//TODO Trigger snapshot action on the TM
|
||||
//vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DispatchManager::disk_snapshot_revert(
|
||||
int vid,
|
||||
int did,
|
||||
int snap_id,
|
||||
string& error_str)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
VirtualMachine * vm = vmpool->get(vid, true);
|
||||
|
||||
if ( vm == 0 )
|
||||
{
|
||||
oss << "Could not revert to disk 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::POWEROFF ||
|
||||
vm->get_lcm_state() != VirtualMachine::LCM_INIT )
|
||||
{
|
||||
oss << "Could not revert to disk snapshot for VM " << vid
|
||||
<< ", wrong state " << vm->state_str() << ".";
|
||||
error_str = oss.str();
|
||||
|
||||
NebulaLog::log("DiM", Log::ERROR, error_str);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//TODO set state (reuse HOTPLUG_SNAPSHOT?)
|
||||
//vm->set_state(VirtualMachine::HOTPLUG_SNAPSHOT);
|
||||
|
||||
if (vm->revert_disk_snapshot(did, snap_id, error_str) == -1)
|
||||
{
|
||||
vm->unlock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
vmpool->update(vm);
|
||||
|
||||
//TODO Regenerate Deployment FILE (and send it to host?)
|
||||
//vmm->trigger(VirtualMachineManager::SNAPSHOT_CREATE,vid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -44,7 +44,9 @@ module OpenNebula
|
||||
:snapshotdelete => "vm.snapshotdelete",
|
||||
:attachnic => "vm.attachnic",
|
||||
:detachnic => "vm.detachnic",
|
||||
:recover => "vm.recover"
|
||||
:recover => "vm.recover",
|
||||
:disksnapshotcreate => "vm.disksnapshotcreate",
|
||||
:disksnapshotrevert => "vm.disksnapshotrevert"
|
||||
}
|
||||
|
||||
VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED
|
||||
@ -610,6 +612,27 @@ module OpenNebula
|
||||
return call(VM_METHODS[:snapshotdelete], @pe_id, snap_id)
|
||||
end
|
||||
|
||||
# Takes a new snapshot of a disk
|
||||
#
|
||||
# @param disk_id [Integer] Id of the disk
|
||||
# @param tag [String] description for the snapshot
|
||||
#
|
||||
# @return [Integer, OpenNebula::Error] The new snapshot ID or error
|
||||
def disk_snapshot_create(disk_id, tag)
|
||||
return call(VM_METHODS[:disksnapshotcreate], @pe_id, disk_id, tag)
|
||||
end
|
||||
|
||||
# Reverts disk state to a previously taken snapshot
|
||||
#
|
||||
# @param disk_id [Integer] Id of the disk
|
||||
# @param snap_id [Integer] Id of the snapshot
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def disk_snapshot_revert(disk_id, snap_id)
|
||||
return call(VM_METHODS[:disksnapshotrevert], @pe_id, disk_id, snap_id)
|
||||
end
|
||||
|
||||
# Recovers an ACTIVE VM
|
||||
#
|
||||
# @param result [Integer] Recover with failure (0), success (1) or
|
||||
|
@ -304,6 +304,8 @@ void RequestManager::register_xml_methods()
|
||||
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_dsnap_create(new VirtualMachineDiskSnapshotCreate());
|
||||
xmlrpc_c::methodPtr vm_dsnap_revert(new VirtualMachineDiskSnapshotRevert());
|
||||
xmlrpc_c::methodPtr vm_recover(new VirtualMachineRecover());
|
||||
|
||||
xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting());
|
||||
@ -460,6 +462,8 @@ void RequestManager::register_xml_methods()
|
||||
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.vm.disksnapshotcreate", vm_dsnap_create);
|
||||
RequestManagerRegistry.addMethod("one.vm.disksnapshotrevert", vm_dsnap_revert);
|
||||
RequestManagerRegistry.addMethod("one.vm.recover", vm_recover);
|
||||
|
||||
RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
|
||||
|
@ -2483,3 +2483,82 @@ void VirtualMachinePoolCalculateShowback::request_execute(
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineDiskSnapshotCreate::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));
|
||||
int did = xmlrpc_c::value_int(paramList.getInt(2));
|
||||
string tag = xmlrpc_c::value_string(paramList.getString(3));
|
||||
|
||||
if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rc = dm->disk_snapshot_create(id, did, tag, snap_id, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
failure_response(ACTION,
|
||||
request_error(error_str, ""),
|
||||
att);
|
||||
}
|
||||
else
|
||||
{
|
||||
success_response(snap_id, att);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineDiskSnapshotRevert::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 did = xmlrpc_c::value_int(paramList.getInt(2));
|
||||
int snap_id = xmlrpc_c::value_int(paramList.getInt(3));
|
||||
|
||||
if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rc = dm->disk_snapshot_revert(id, did, snap_id, error_str);
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
failure_response(ACTION,
|
||||
request_error(error_str, ""),
|
||||
att);
|
||||
}
|
||||
else
|
||||
{
|
||||
success_response(id, att);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -14,13 +14,13 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "Snapshot.h"
|
||||
#include "Snapshots.h"
|
||||
|
||||
Snapshots::Snapshots(int _disk_id):
|
||||
snapshot_template(false,'=',"SNAPSHOTS"),
|
||||
next_snapshot(0),
|
||||
disk_id(_disk_id),
|
||||
active(-1)
|
||||
next_snapshot(1),
|
||||
active(0),
|
||||
disk_id(_disk_id)
|
||||
{
|
||||
snapshot_template.add("DISK_ID",_disk_id);
|
||||
};
|
||||
@ -71,7 +71,7 @@ int Snapshots::from_xml_node(const xmlNodePtr node)
|
||||
|
||||
if (snapshot_template.get("DISK_ID", did))
|
||||
{
|
||||
disk_id = id;
|
||||
disk_id = did;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -80,23 +80,22 @@ int Snapshots::from_xml_node(const xmlNodePtr node)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Snapshots::create_snapshot(unsigned int p_id, const string& tag,
|
||||
string& error)
|
||||
int Snapshots::create_snapshot(const string& disk_src, const string& tag)
|
||||
{
|
||||
VectorAttribute * parent = get_snapshot(p_id);
|
||||
string source;
|
||||
int parent_id;
|
||||
|
||||
if (parent == 0)
|
||||
if ( active > 0 )
|
||||
{
|
||||
error = "Parent snapshot not found.";
|
||||
return -1;
|
||||
VectorAttribute * parent = get_snapshot(active);
|
||||
|
||||
source = parent->vector_value("SOURCE");
|
||||
parent_id = active;
|
||||
}
|
||||
|
||||
string psource = parent->vector_value("SOURCE");
|
||||
|
||||
if (psource.empty())
|
||||
else
|
||||
{
|
||||
error = "Parent snapshot has no source.";
|
||||
return -1;
|
||||
source = disk_src;
|
||||
parent_id = 0;
|
||||
}
|
||||
|
||||
VectorAttribute * snapshot = new VectorAttribute("SNAPSHOT");
|
||||
@ -106,17 +105,17 @@ int Snapshots::create_snapshot(unsigned int p_id, const string& tag,
|
||||
snapshot->replace("TAG",tag);
|
||||
}
|
||||
|
||||
snapshot->replace("ID", next_snapshot++);
|
||||
|
||||
snapshot->replace("ID", next_snapshot);
|
||||
snapshot->replace("DATE", static_cast<long long>(time(0)));
|
||||
|
||||
snapshot->replace("PARENT", psource);
|
||||
snapshot->replace("PARENT_ID", parent_id);
|
||||
snapshot->replace("PARENT", source);
|
||||
|
||||
snapshot_template.set(snapshot);
|
||||
|
||||
snapshot_pool.insert(pair<unsigned int, VectorAttribute *>(next_snapshot, snapshot));
|
||||
snapshot_pool.insert(
|
||||
pair<unsigned int, VectorAttribute *>(next_snapshot, snapshot));
|
||||
|
||||
return next_snapshot;
|
||||
return next_snapshot++;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -152,16 +151,27 @@ int Snapshots::delete_snapshot(unsigned int id)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int Snapshots::active_snapshot(unsigned int id)
|
||||
int Snapshots::active_snapshot(unsigned int id, string& error)
|
||||
{
|
||||
VectorAttribute * snapshot = get_snapshot(id);
|
||||
VectorAttribute * snapshot;
|
||||
|
||||
if (snapshot == 0)
|
||||
if ( id == active )
|
||||
{
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
snapshot->replace("ACTIVE", true);
|
||||
if ( id != 0 )
|
||||
{
|
||||
snapshot = get_snapshot(id);
|
||||
|
||||
if (snapshot == 0)
|
||||
{
|
||||
error = "Snapshot does not exists";
|
||||
return -1;
|
||||
}
|
||||
|
||||
snapshot->replace("ACTIVE", true);
|
||||
}
|
||||
|
||||
snapshot = get_snapshot(active);
|
||||
|
||||
@ -175,7 +185,6 @@ int Snapshots::active_snapshot(unsigned int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ImagePool.h"
|
||||
#include "NebulaLog.h"
|
||||
#include "NebulaUtil.h"
|
||||
#include "Snapshots.h"
|
||||
|
||||
#include "Nebula.h"
|
||||
|
||||
@ -89,6 +90,12 @@ VirtualMachine::~VirtualMachine()
|
||||
delete history_records[i];
|
||||
}
|
||||
|
||||
for (map<int, Snapshots *>::const_iterator it = snapshots.begin();
|
||||
it != snapshots.end() ; it++)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
delete _log;
|
||||
delete obj_template;
|
||||
delete user_obj_template;
|
||||
@ -883,12 +890,12 @@ int VirtualMachine::parse_context(string& error_str)
|
||||
continue;
|
||||
}
|
||||
|
||||
parse_context_network(NETWORK_CONTEXT, NUM_NETWORK_CONTEXT,
|
||||
parse_context_network(NETWORK_CONTEXT, NUM_NETWORK_CONTEXT,
|
||||
context, vatt);
|
||||
|
||||
if (!vatt->vector_value("IP6_GLOBAL").empty())
|
||||
{
|
||||
parse_context_network(NETWORK6_CONTEXT, NUM_NETWORK6_CONTEXT,
|
||||
parse_context_network(NETWORK6_CONTEXT, NUM_NETWORK6_CONTEXT,
|
||||
context, vatt);
|
||||
}
|
||||
}
|
||||
@ -2987,7 +2994,8 @@ void VirtualMachine::release_security_groups(int id, VectorAttribute const * nic
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::generate_context(string &files, int &disk_id, string& token_password)
|
||||
int VirtualMachine::generate_context(string &files, int &disk_id,
|
||||
string& token_password)
|
||||
{
|
||||
ofstream file;
|
||||
string files_ds;
|
||||
@ -3418,7 +3426,8 @@ int VirtualMachine::save_disk_hot(int disk_id,
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source, int& image_id)
|
||||
int VirtualMachine::get_saveas_disk_hot(int& disk_id, string& source,
|
||||
int& image_id)
|
||||
{
|
||||
vector<Attribute *> disks;
|
||||
VectorAttribute * disk;
|
||||
@ -3731,6 +3740,8 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const
|
||||
string user_template_xml;
|
||||
string history_xml;
|
||||
string perm_xml;
|
||||
string snap_xml;
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
oss << "<VM>"
|
||||
@ -3780,6 +3791,12 @@ string& VirtualMachine::to_xml_extended(string& xml, int n_history) const
|
||||
oss << "<HISTORY_RECORDS/>";
|
||||
}
|
||||
|
||||
for (map<int, Snapshots *>::const_iterator it = snapshots.begin();
|
||||
it != snapshots.end() ; it++)
|
||||
{
|
||||
oss << it->second->to_xml(snap_xml);
|
||||
}
|
||||
|
||||
oss << "</VM>";
|
||||
|
||||
xml = oss.str();
|
||||
@ -3878,6 +3895,32 @@ int VirtualMachine::from_xml(const string &xml_str)
|
||||
history_records[history->seq] = history;
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
content.clear();
|
||||
}
|
||||
|
||||
// Virtual Machine user template
|
||||
|
||||
ObjectXML::get_nodes("/VM/SNAPSHOTS", content);
|
||||
|
||||
for (vector<xmlNodePtr>::iterator it=content.begin();it!=content.end();it++)
|
||||
{
|
||||
Snapshots * snap = new Snapshots(-1);
|
||||
|
||||
rc += snap->from_xml_node(*it);
|
||||
|
||||
if ( rc != 0)
|
||||
{
|
||||
delete snap;
|
||||
break;
|
||||
}
|
||||
|
||||
snapshots.insert(pair<int, Snapshots *>(snap->get_disk_id(), snap));
|
||||
}
|
||||
|
||||
if (!content.empty())
|
||||
{
|
||||
ObjectXML::free_nodes(content);
|
||||
content.clear();
|
||||
}
|
||||
|
||||
if (rc != 0)
|
||||
@ -4078,7 +4121,8 @@ void VirtualMachine::clear_template_monitor_error()
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::get_public_cloud_hypervisors(vector<string> &public_cloud_hypervisors) const
|
||||
int VirtualMachine::get_public_cloud_hypervisors(
|
||||
vector<string> &public_cloud_hypervisors) const
|
||||
{
|
||||
vector<Attribute*> attrs;
|
||||
vector<Attribute*>::const_iterator it;
|
||||
@ -4116,3 +4160,76 @@ int VirtualMachine::get_public_cloud_hypervisors(vector<string> &public_cloud_hy
|
||||
|
||||
return public_cloud_hypervisors.size();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::new_disk_snapshot(int did, const string& tag, string& error)
|
||||
{
|
||||
map<int, Snapshots *>::iterator it;
|
||||
int snap_id;
|
||||
|
||||
VectorAttribute * disk;
|
||||
string source;
|
||||
|
||||
disk = get_disk(did);
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
error = "DISK does not exists";
|
||||
return -1;
|
||||
}
|
||||
|
||||
source = disk->vector_value("SOURCE");
|
||||
|
||||
it = snapshots.find(did);
|
||||
|
||||
if ( it == snapshots.end() )
|
||||
{
|
||||
Snapshots * snap = new Snapshots(did);
|
||||
|
||||
snap_id = snap->create_snapshot(source, tag);
|
||||
|
||||
snapshots.insert(pair<int, Snapshots *>(did, snap));
|
||||
}
|
||||
else
|
||||
{
|
||||
snap_id = it->second->create_snapshot(source, tag);
|
||||
}
|
||||
|
||||
return snap_id;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachine::revert_disk_snapshot(int did, int snap_id, string& error)
|
||||
{
|
||||
map<int, Snapshots *>::iterator it;
|
||||
int rc;
|
||||
|
||||
VectorAttribute * disk;
|
||||
string source;
|
||||
|
||||
disk = get_disk(did);
|
||||
|
||||
if ( disk == 0 )
|
||||
{
|
||||
error = "DISK does not exists";
|
||||
return -1;
|
||||
}
|
||||
|
||||
it = snapshots.find(did);
|
||||
|
||||
if ( it == snapshots.end() && snap_id != 0 )
|
||||
{
|
||||
error = "Snapshot does not exists";
|
||||
return -1;
|
||||
}
|
||||
else if ( it != snapshots.end() )
|
||||
{
|
||||
rc = it->second->active_snapshot(snap_id, error);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user