1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-23 22:50:09 +03:00

Feature #3782: Add image snapshots to sunstone

This commit is contained in:
Carlos Martín 2015-06-30 16:13:38 +02:00
parent 979aa0d00a
commit c9fc7a36da
13 changed files with 254 additions and 5 deletions

View File

@ -236,6 +236,7 @@ tabs:
panel_tabs:
image_info_tab: true
image_vms_tab: true
image_snapshots_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
@ -262,6 +263,9 @@ tabs:
Image.nonpersistent: true
Image.clone_dialog: true
Image.delete: true
Image.snapshot_flatten: true
Image.snapshot_revert: true
Image.snapshot_delete: true
files-tab:
panel_tabs:
file_info_tab: true

View File

@ -236,6 +236,7 @@ tabs:
panel_tabs:
image_info_tab: true
image_vms_tab: true
image_snapshots_tab: false
table_columns:
- 0 # Checkbox
- 1 # ID
@ -262,6 +263,9 @@ tabs:
Image.nonpersistent: true
Image.clone_dialog: true
Image.delete: true
Image.snapshot_flatten: false
Image.snapshot_revert: false
Image.snapshot_delete: false
files-tab:
panel_tabs:
file_info_tab: true

View File

@ -237,6 +237,7 @@ tabs:
panel_tabs:
image_info_tab: true
image_vms_tab: true
image_snapshots_tab: true
table_columns:
- 0 # Checkbox
- 1 # ID
@ -263,6 +264,9 @@ tabs:
Image.nonpersistent: true
Image.clone_dialog: true
Image.delete: true
Image.snapshot_flatten: true
Image.snapshot_revert: true
Image.snapshot_delete: true
files-tab:
panel_tabs:
file_info_tab: true

View File

@ -60,6 +60,9 @@ module OpenNebulaJSON
when "chtype" then self.chtype(action_hash['params'])
when "clone" then self.clone(action_hash['params'])
when "rename" then self.rename(action_hash['params'])
when "snapshot_flatten" then self.snapshot_flatten(action_hash['params'])
when "snapshot_revert" then self.snapshot_revert(action_hash['params'])
when "snapshot_delete" then self.snapshot_delete(action_hash['params'])
else
error_msg = "#{action_hash['perform']} action not " <<
" available for this resource"
@ -110,5 +113,17 @@ module OpenNebulaJSON
def rename(params=Hash.new)
super(params['name'])
end
def snapshot_flatten(params=Hash.new)
super(params['snapshot_id'].to_i)
end
def snapshot_revert(params=Hash.new)
super(params['snapshot_id'].to_i)
end
def snapshot_delete(params=Hash.new)
super(params['snapshot_id'].to_i)
end
end
end

View File

@ -108,6 +108,18 @@ define(function(require) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "rename", action_obj);
},
"snapshot_flatten": function(params) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "snapshot_flatten", action_obj);
},
"snapshot_revert": function(params) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "snapshot_revert", action_obj);
},
"snapshot_delete": function(params) {
var action_obj = params.data.extra_param;
OpenNebulaAction.simple_action(params, RESOURCE, "snapshot_delete", action_obj);
},
"getName": function(id){
return OpenNebulaAction.getName(id, RESOURCE);
}

View File

@ -13,7 +13,8 @@ define(function(require) {
var _panels = [
require('./images-tab/panels/info'),
require('./images-tab/panels/vms')
require('./images-tab/panels/vms'),
require('./images-tab/panels/snapshots')
];
var _formPanels = [

View File

@ -3,6 +3,7 @@ define(function(require) {
var Notifier = require('utils/notifier');
var Locale = require('utils/locale');
var OpenNebulaImage = require('opennebula/image');
var CommonActions = require('utils/common-actions');
var RESOURCE = "Image";
var XML_ROOT = "IMAGE";
@ -10,6 +11,8 @@ define(function(require) {
var CREATE_DIALOG_ID = require('./form-panels/create/formPanelId');
var CLONE_DIALOG_ID = require('./dialogs/clone/dialogId');
var _commonActions = new CommonActions(OpenNebulaImage, RESOURCE, TAB_ID);
var _actions = {
"Image.create" : {
type: "create",
@ -209,7 +212,10 @@ define(function(require) {
},
error: Notifier.onError,
notify: true
}
},
"Image.snapshot_flatten": _commonActions.singleAction("snapshot_flatten"),
"Image.snapshot_revert": _commonActions.singleAction("snapshot_revert"),
"Image.snapshot_delete": _commonActions.singleAction("snapshot_delete"),
};
return _actions;

View File

@ -0,0 +1,174 @@
define(function(require){
/*
DEPENDENCIES
*/
var Locale = require('utils/locale');
var Humanize = require('utils/humanize');
var Config = require('sunstone-config');
var Sunstone = require('sunstone');
var Tree = require('utils/tree');
var TemplateHtml = require('hbs!./snapshots/html');
var TemplateEmptyTable = require('hbs!utils/tab-datatable/empty-table');
/*
CONSTANTS
*/
var PANEL_ID = require('./snapshots/panelId');
var RESOURCE = "Image";
var XML_ROOT = "IMAGE";
/*
CONSTRUCTOR
*/
function Panel(info) {
this.title = Locale.tr("Snapshots");
this.icon = "fa-camera";
this.element = info[XML_ROOT];
return this;
}
Panel.PANEL_ID = PANEL_ID;
Panel.prototype.html = _html;
Panel.prototype.setup = _setup;
return Panel;
/*
FUNCTION DEFINITIONS
*/
function _html() {
var snapshotsHTML = TemplateEmptyTable();
if (!$.isEmptyObject(this.element.SNAPSHOTS)){
var snapshots = this.element.SNAPSHOTS.SNAPSHOT;
if (!$.isArray(snapshots)){
snapshots = [snapshots];
}
var treeRoot = {
htmlStr : '',
subTree : []
};
var indexedSnapshots = {};
var noParent = [];
$.each(snapshots, function(){
indexedSnapshots[this.ID] = this;
if(this.PARENT == "-1"){
noParent.push(this.ID);
}
});
$.each(noParent, function(){
treeRoot.subTree.push(
_makeTree(indexedSnapshots[this], indexedSnapshots)
);
});
snapshotsHTML = Tree.html(treeRoot);
}
return TemplateHtml({snapshotsHTML: snapshotsHTML});
}
function _setup(context) {
var that = this;
$(".snapshot_check_item", context).on("change", function() {
// Unselect other check inputs
var checked = $(this).is(':checked');
$('.snapshot_check_item:checked', context).prop('checked', false);
$(this).prop('checked', checked);
// Enable/disable buttons
if ($(this).is(":checked")) {
$("#snapshot_flatten", context).prop('disabled', false);
$("#snapshot_revert", context).prop('disabled', false);
$("#snapshot_delete", context).prop('disabled', false);
} else {
$("#snapshot_flatten", context).prop('disabled', true);
$("#snapshot_revert", context).prop('disabled', true);
$("#snapshot_delete", context).prop('disabled', true);
}
});
if (Config.isTabActionEnabled("images-tab", "Image.snapshot_flatten")) {
$("#snapshot_flatten", context).on('click', function() {
var snapshot_id = $(".snapshot_check_item:checked", context).attr('snapshot_id');
Sunstone.runAction('Image.snapshot_flatten', that.element.ID,
{ "snapshot_id": snapshot_id});
return false;
});
}
if (Config.isTabActionEnabled("images-tab", "Image.snapshot_revert")) {
$("#snapshot_revert", context).on('click', function() {
var snapshot_id = $(".snapshot_check_item:checked", context).attr('snapshot_id');
Sunstone.runAction('Image.snapshot_revert', that.element.ID,
{ "snapshot_id": snapshot_id});
return false;
});
}
if (Config.isTabActionEnabled("images-tab", "Image.snapshot_delete")) {
$("#snapshot_delete", context).on('click', function() {
var snapshot_id = $(".snapshot_check_item:checked", context).attr('snapshot_id');
Sunstone.runAction('Image.snapshot_delete', that.element.ID,
{ "snapshot_id": snapshot_id});
return false;
});
}
return false;
}
function _makeTree(snapshot, indexedSnapshots){
var SPACE = '&nbsp;&nbsp;&nbsp;&nbsp;';
var subTree = [];
if (snapshot.CHILDREN){
$.each(snapshot.CHILDREN.split(","), function(){
subTree.push(
_makeTree(indexedSnapshots[this], indexedSnapshots)
);
});
}
var html = '<div class="snapshot_row nowrap">'+
'<input class="snapshot_check_item" type="checkbox" snapshot_id="'+snapshot.ID+'"/>'+
SPACE + snapshot.ID + SPACE;
var active = (snapshot.ACTIVE == "YES");
if(active){
html += '<i class="fa fa-play-circle-o fa-lg" data-tooltip title="'+
Locale.tr("Active")+'"/>' + SPACE;
}
html += Humanize.prettyTime(snapshot.DATE) + SPACE +
(snapshot.TAG ? snapshot.TAG + SPACE : '');
html += '</div>';
return {
htmlStr : html,
subTree : subTree
};
}
});

View File

@ -0,0 +1,26 @@
<div class="row collapse">
<div class="large-12 columns">
<span class="right">
{{#isTabActionEnabled "images-tab" "Image.snapshot_flatten"}}
<button class="button secondary small radius" id="snapshot_flatten" disabled="disabled">
<span class="fa fa-sort-amount-asc"></span>{{tr "Flatten"}}
</button>
{{/isTabActionEnabled}}
{{#isTabActionEnabled "images-tab" "Image.snapshot_revert"}}
<button class="button secondary small radius" id="snapshot_revert" disabled="disabled">
<span class="fa fa-reply"></span>{{tr "Revert"}}
</button>
{{/isTabActionEnabled}}
{{#isTabActionEnabled "images-tab" "Image.snapshot_delete"}}
<button class="button secondary small radius" id="snapshot_delete" disabled="disabled">
<span class="fa fa-times"></span>{{tr "Delete"}}
</button>
{{/isTabActionEnabled}}
</span>
</div>
</div>
<div class="row collapse">
<div class="large-12 columns" style="overflow-x:auto">
{{{snapshotsHTML}}}
</div>
</div>

View File

@ -0,0 +1,3 @@
define(function(require){
return 'image_snapshots_tab';
});

View File

@ -263,7 +263,8 @@ define(function(require) {
$(this).children("span").addClass('fa-chevron-down');
$(this).children("span").removeClass('fa-chevron-up');
} else {
var html = '<div class="snapshots" disk_id='+row.data().DISK_ID+' style="padding-left: 30px;">'+
var html = '<div class="snapshots" disk_id='+row.data().DISK_ID+
' style="padding-left: 30px; width:900px; overflow-x:auto">'+
row.data().SNAPSHOTS+
'</div>';

File diff suppressed because one or more lines are too long

View File

@ -1262,7 +1262,6 @@ hr {
margin-left: 1em;
padding: 0;
position: relative;
overflow:hidden;
}
.tree li{