1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-25 02:50:08 +03:00

feature #3782: Flatten action for Images

This commit is contained in:
Ruben S. Montero 2015-06-05 16:01:06 +02:00
parent 0bbb99a240
commit 08356ed8c3
10 changed files with 237 additions and 4 deletions

View File

@ -496,6 +496,14 @@ public:
return snapshots;
};
/**
* Clear all the snapshots in the list
*/
void clear_snapshots()
{
snapshots.clear();
}
/**
* Set the snapshots for this image
* @param snapshot list

View File

@ -217,6 +217,15 @@ public:
*/
int revert_snapshot(int iid, int sid, string& error);
/**
* Flattens ths snapshot by commiting changes to base image.
* @param iid id of image
* @param sid id of the snapshot
* @param error_str Error reason, if any
* @return 0 on success
*/
int flatten_snapshot(int iid, int sid, string& error);
private:
/**
* Generic name for the Image driver

View File

@ -100,6 +100,19 @@ public:
*/
int active_snapshot(unsigned int id);
/**
* Clear all the snapshots in the list
*/
void clear()
{
next_snapshot = 0;
active = -1;
disk_id = -1;
snapshot_template.clear();
snapshot_pool.clear();
}
/**
* Return the disk_id of the snapshot list
*/

View File

@ -321,6 +321,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
end
end
snapshot_flatten_desc = <<-EOT.unindent
Flattens the snapshot and removes all other snapshots in the image
EOT
command :"snapshot-flatten", snapshot_flatten_desc, :imageid, :snapshot_id do
helper.perform_action(args[0], options, "snapshot flattened") do |o|
o.snapshot_flatten(args[1].to_i)
end
end
list_desc = <<-EOT.unindent
Lists Images in the pool
EOT

View File

@ -52,7 +52,8 @@ class DatastoreDriver < OpenNebulaDriver
:clone => "CLONE",
:monitor => "MONITOR",
:snap_delete => "SNAP_DELETE",
:snap_revert => "SNAP_REVERT"
:snap_revert => "SNAP_REVERT",
:snap_flatten=> "SNAP_FLATTEN"
}
# Register default actions for the protocol
@ -69,7 +70,8 @@ class DatastoreDriver < OpenNebulaDriver
ACTION[:clone] => nil,
ACTION[:monitor] => nil,
ACTION[:snap_delete] => nil,
ACTION[:snap_revert] => nil
ACTION[:snap_revert] => nil,
ACTION[:snap_flatten] => nil
}
}.merge!(options)
@ -93,6 +95,7 @@ class DatastoreDriver < OpenNebulaDriver
register_action(ACTION[:monitor].to_sym, method("monitor"))
register_action(ACTION[:snap_delete].to_sym, method("snap_delete"))
register_action(ACTION[:snap_revert].to_sym, method("snap_revert"))
register_action(ACTION[:snap_flatten].to_sym, method("snap_flatten"))
end
############################################################################
@ -139,6 +142,11 @@ class DatastoreDriver < OpenNebulaDriver
do_image_action(id, ds, :snap_revert, "#{drv_message} #{id}")
end
def snap_flatten(id, drv_message)
ds = get_ds_type(drv_message)
do_image_action(id, ds, :snap_flatten, "#{drv_message} #{id}")
end
private
def is_available?(ds, id, action)

View File

@ -1129,3 +1129,99 @@ int ImageManager::revert_snapshot(int iid, int sid, string& error)
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImageManager::flatten_snapshot(int iid, int sid, string& error)
{
const ImageManagerDriver* imd = get();
if ( imd == 0 )
{
error = "Could not get datastore driver";
NebulaLog::log("ImM",Log::ERROR, error);
return -1;
}
/* ---------------------------------------------------------------------- */
/* Check action consistency: */
/* state is READY */
/* snapshot exists */
/* ---------------------------------------------------------------------- */
Image * img = ipool->get(iid,true);
if ( img == 0 )
{
error = "Image does not exist";
return -1;
}
if (img->get_state() != Image::READY)
{
error = "Cannot flatten snapshot in state " + Image::state_to_str(img->get_state());
img->unlock();
return -1;
}
const Snapshots& snaps = img->get_snapshots();
if (!snaps.exists(sid))
{
error = "Snapshot does not exist";
img->unlock();
return -1;
}
/* ---------------------------------------------------------------------- */
/* Get DS data for driver */
/* ---------------------------------------------------------------------- */
int ds_id = img->get_ds_id();
img->unlock();
string ds_data;
Datastore * ds = dspool->get(ds_id, true);
if ( ds == 0 )
{
error = "Datastore no longer exists";
return -1;
}
ds->to_xml(ds_data);
ds->unlock();
/* ---------------------------------------------------------------------- */
/* Format message and send action to driver */
/* ---------------------------------------------------------------------- */
img = ipool->get(iid,true);
if ( img == 0 )
{
error = "Image does not exist";
return -1;
}
img->set_target_snapshot(sid);
string img_tmpl;
string * drv_msg = format_message(img->to_xml(img_tmpl), ds_data);
imd->snapshot_flatten(iid, *drv_msg);
img->set_state(Image::LOCKED);
ipool->update(img);
img->unlock();
delete drv_msg;
return 0;
}

View File

@ -815,6 +815,52 @@ static void snap_revert_action(istringstream& is,
image->unlock();
}
/* -------------------------------------------------------------------------- */
static void snap_flatten_action(istringstream& is,
ImagePool* ipool,
int id,
const string& result)
{
ostringstream oss;
string info;
Image * image = ipool->get(id, true);
if ( image == 0 )
{
return;
}
if ( result == "SUCCESS")
{
image->clear_snapshots();
}
else
{
oss << "Error flattening image snapshot";
getline(is, info);
if (!info.empty() && (info[0] != '-'))
{
oss << ": " << info;
}
image->set_template_error_message(oss.str());
NebulaLog::log("ImM", Log::ERROR, oss);
}
image->set_state(Image::READY);
image->clear_target_snapshot();
ipool->update(image);
image->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -898,6 +944,10 @@ void ImageManagerDriver::protocol(const string& message) const
{
snap_revert_action(is, ipool, id, result);
}
else if (action == "SNAP_FLATTEN")
{
snap_flatten_action(is, ipool, id, result);
}
else if (action == "LOG")
{
getline(is,info);

View File

@ -37,7 +37,8 @@ module OpenNebula
:clone => "image.clone",
:rename => "image.rename",
:snapshotdelete => "image.snapshotdelete",
:snapshotrevert => "image.snapshotrevert"
:snapshotrevert => "image.snapshotrevert",
:snapshotflatten=> "image.snapshotflatten"
}
IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS}
@ -243,6 +244,14 @@ module OpenNebula
return call(IMAGE_METHODS[:snapshotrevert], @pe_id, snap_id)
end
# Flattens an image snapshot
#
# @param snap_id [Integet] ID of the snapshot to flatten
#
# @return [nil, OpenNebula::Error] nil in case of success or Error
def snapshot_flatten(snap_id)
return call(IMAGE_METHODS[:snapshotflatten], @pe_id, snap_id)
end
#######################################################################
# Helpers to get Image information
#######################################################################

View File

@ -399,6 +399,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr image_clone(new ImageClone());
xmlrpc_c::methodPtr image_snap_delete(new ImageSnapshotDelete());
xmlrpc_c::methodPtr image_snap_revert(new ImageSnapshotRevert());
xmlrpc_c::methodPtr image_snap_flatten(new ImageSnapshotFlatten());
// Datastore Methods
xmlrpc_c::methodPtr datastore_enable(new DatastoreEnable());
@ -657,6 +658,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.image.rename", image_rename);
RequestManagerRegistry.addMethod("one.image.snapshotdelete", image_snap_delete);
RequestManagerRegistry.addMethod("one.image.snapshotrevert", image_snap_revert);
RequestManagerRegistry.addMethod("one.image.snapshotflatten", image_snap_flatten);
RequestManagerRegistry.addMethod("one.imagepool.info", imagepool_info);

View File

@ -498,7 +498,6 @@ void ImageSnapshotDelete::request_execute(xmlrpc_c::paramList const& paramList,
success_response(id, att);
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
@ -528,3 +527,32 @@ void ImageSnapshotRevert::request_execute(xmlrpc_c::paramList const& paramList,
success_response(id, att);
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void ImageSnapshotFlatten::request_execute(xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
{
int id = xmlrpc_c::value_int(paramList.getInt(1));
int snap_id = xmlrpc_c::value_int(paramList.getInt(2));
Nebula& nd = Nebula::instance();
ImageManager * imagem = nd.get_imagem();
if ( basic_authorization(id, att) == false )
{
return;
}
string err_msg;
int rc = imagem->flatten_snapshot(id, snap_id, err_msg);
if ( rc < 0 )
{
failure_response(ACTION, request_error(err_msg, ""), att);
return;
}
success_response(id, att);
}