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

feature #3782: Revert action for images

This commit is contained in:
Ruben S. Montero 2015-06-05 04:45:20 +02:00
parent 78c7bdbd5d
commit 9348a0d455
9 changed files with 209 additions and 9 deletions

View File

@ -201,13 +201,22 @@ public:
/**
* Deletes the snapshot of an image
* @param iid id of image
* @param sid id of the snapshot
* @param error_str Error reason, if any
* @return 0 on success
* @param iid id of image
* @param sid id of the snapshot
* @param error_str Error reason, if any
* @return 0 on success
*/
int delete_snapshot(int iid, int sid, string& error);
/**
* Reverts image state to a previous snapshot
* @param iid id of image
* @param sid id of the snapshot
* @param error_str Error reason, if any
* @return 0 on success
*/
int revert_snapshot(int iid, int sid, string& error);
private:
/**
* Generic name for the Image driver

View File

@ -128,7 +128,7 @@ public:
ImageSnapshotRevert():
RequestManagerImage("ImageSnapshotRevert",
"Reverts image state to a previous snapshot",
"A:sis"){};
"A:sii"){};
~ImageSnapshotRevert(){};

View File

@ -311,6 +311,16 @@ cmd=CommandParser::CmdParser.new(ARGV) do
end
end
snapshot_revert_desc = <<-EOT.unindent
Reverts image state to a snapshot
EOT
command :"snapshot-revert", snapshot_revert_desc, :imageid, :snapshot_id do
helper.perform_action(args[0], options, "image state reverted") do |o|
o.snapshot_revert(args[1].to_i)
end
end
list_desc = <<-EOT.unindent
Lists Images in the pool
EOT

View File

@ -51,7 +51,8 @@ class DatastoreDriver < OpenNebulaDriver
:stat => "STAT",
:clone => "CLONE",
:monitor => "MONITOR",
:snap_delete => "SNAP_DELETE"
:snap_delete => "SNAP_DELETE",
:snap_revert => "SNAP_REVERT"
}
# Register default actions for the protocol
@ -67,7 +68,8 @@ class DatastoreDriver < OpenNebulaDriver
ACTION[:mkfs] => nil,
ACTION[:clone] => nil,
ACTION[:monitor] => nil,
ACTION[:snap_delete] => nil
ACTION[:snap_delete] => nil,
ACTION[:snap_revert] => nil
}
}.merge!(options)
@ -90,6 +92,7 @@ class DatastoreDriver < OpenNebulaDriver
register_action(ACTION[:clone].to_sym, method("clone"))
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"))
end
############################################################################
@ -131,6 +134,11 @@ class DatastoreDriver < OpenNebulaDriver
do_image_action(id, ds, :snap_delete, "#{drv_message} #{id}")
end
def snap_revert(id, drv_message)
ds = get_ds_type(drv_message)
do_image_action(id, ds, :snap_revert, "#{drv_message} #{id}")
end
private
def is_available?(ds, id, action)

View File

@ -1015,4 +1015,78 @@ int ImageManager::delete_snapshot(int iid, int sid, string& error)
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int ImageManager::revert_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;
}
Image * img = ipool->get(iid,true);
if ( img == 0 )
{
error = "Image does not exist";
return -1;
}
const Snapshots& snaps = img->get_snapshots();
if (snaps.get_active_id() == sid)
{
error = "Snapshot is already the active one";
img->unlock();
return -1;
}
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();
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_revert(iid, *drv_msg);
ipool->update(img);
img->unlock();
delete drv_msg;
return 0;
}

View File

@ -753,6 +753,60 @@ static void snap_delete_action(istringstream& is,
image->unlock();
}
/* -------------------------------------------------------------------------- */
static void snap_revert_action(istringstream& is,
ImagePool* ipool,
int id,
const string& result)
{
ostringstream oss;
string info;
Image * image = ipool->get(id, true);
if ( image == 0 )
{
return;
}
int snap_id = image->get_target_snapshot();
if (snap_id == -1)
{
NebulaLog::log("ImM", Log::ERROR, "No target snapshot in callback");
image->unlock();
return;
}
if ( result == "SUCCESS")
{
image->revert_snapshot(snap_id);
}
else
{
oss << "Error reverting image " << id << " to snapshot " << snap_id;
getline(is, info);
if (!info.empty() && (info[0] != '-'))
{
oss << ": " << info;
}
image->set_template_error_message(oss.str());
NebulaLog::log("ImM", Log::ERROR, oss);
}
image->clear_target_snapshot();
ipool->update(image);
image->unlock();
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
@ -832,6 +886,10 @@ void ImageManagerDriver::protocol(const string& message) const
{
snap_delete_action(is, ipool, id, result);
}
else if (action == "SNAP_REVERT")
{
snap_revert_action(is, ipool, id, result);
}
else if (action == "LOG")
{
getline(is,info);

View File

@ -24,7 +24,6 @@ module OpenNebula
# Constants and Class Methods
#######################################################################
IMAGE_METHODS = {
:info => "image.info",
:allocate => "image.allocate",
@ -37,7 +36,8 @@ module OpenNebula
:chtype => "image.chtype",
:clone => "image.clone",
:rename => "image.rename",
:snapshotdelete => "image.snapshotdelete"
:snapshotdelete => "image.snapshotdelete",
:snapshotrevert => "image.snapshotrevert"
}
IMAGE_STATES=%w{INIT READY USED DISABLED LOCKED ERROR CLONE DELETE USED_PERS}
@ -234,6 +234,15 @@ module OpenNebula
return call(IMAGE_METHODS[:snapshotdelete], @pe_id, snap_id)
end
# Reverts Image state to a previous snapshot
#
# @param snap_id [Integet] ID of the snapshot to delete
#
# @return [nil, OpenNebula::Error] nil in case of success or Error
def snapshot_revert(snap_id)
return call(IMAGE_METHODS[:snapshotrevert], @pe_id, snap_id)
end
#######################################################################
# Helpers to get Image information
#######################################################################

View File

@ -398,6 +398,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr image_chtype(new ImageChangeType());
xmlrpc_c::methodPtr image_clone(new ImageClone());
xmlrpc_c::methodPtr image_snap_delete(new ImageSnapshotDelete());
xmlrpc_c::methodPtr image_snap_revert(new ImageSnapshotRevert());
// Datastore Methods
xmlrpc_c::methodPtr datastore_enable(new DatastoreEnable());
@ -655,6 +656,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.image.clone", image_clone);
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.imagepool.info", imagepool_info);

View File

@ -498,3 +498,33 @@ void ImageSnapshotDelete::request_execute(xmlrpc_c::paramList const& paramList,
success_response(id, att);
}
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
void ImageSnapshotRevert::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->revert_snapshot(id, snap_id, err_msg);
if ( rc < 0 )
{
failure_response(ACTION, request_error(err_msg, ""), att);
return;
}
success_response(id, att);
}