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

B #5355: Update Service Charts (#1246)

Co-authored-by: Jorge Lobo <jlobo@opennebula.systems>
This commit is contained in:
Jorge Miguel Lobo Escalona 2021-05-25 16:47:14 +02:00 committed by GitHub
parent 6c71efc9ad
commit 26c02b657e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 373 additions and 62 deletions

View File

@ -996,7 +996,10 @@ define(function(require) {
timeout: true,
success: callback,
error:err,
data: {monitor: dataArg}});
data: {
monitor: dataArg
}
});
break;
case "monitor":
case "monitor_single":
@ -1037,11 +1040,9 @@ define(function(require) {
call();
}
}
if (notify) {
Notifier.notifySubmit(action, dataArg, extraParam);
}
return 0;
};

View File

@ -13,7 +13,7 @@ the License for the specific language governing permissions and }} {{! limitatio
</td>
</tr>
<tr>
<td colspan="3">{{{sched_actions_table}}}</td>
<td colspan="3" class="sched_place">{{{sched_actions_table}}}</td>
</tr>
<tr>
<td id="title" colspan="3">

View File

@ -19,11 +19,17 @@ define(function(require) {
DEPENDENCIES
*/
var Config = require("sunstone-config");
var Sunstone = require("sunstone");
var Actions = require("opennebula/action");
var Service = require("opennebula/service");
var Locale = require("utils/locale");
var Notifier = require("utils/notifier");
var ScheduleActions = require("utils/schedule_action");
var TemplateUtils = require("utils/template-utils");
var Leases = require("utils/leases");
var OpenNebulaAction = require("../../../opennebula/action");
var Humanize = require("utils/humanize");
/*
TEMPLATES
@ -38,6 +44,7 @@ define(function(require) {
var PANEL_ID = require("./sched-actions/panelId");
var RESOURCE = "Service";
var RESOURCE_SCHED_ACTIONS = "flow";
/*
CONSTRUCTOR
@ -47,7 +54,9 @@ define(function(require) {
this.icon = "fa-calendar-alt";
this.title = Locale.tr("Actions");
this.id = (info && info.DOCUMENT && info.DOCUMENT.ID) || "0";
this.data = (info && info.DOCUMENT && info.DOCUMENT.TEMPLATE && info.DOCUMENT.TEMPLATE.BODY && info.DOCUMENT.TEMPLATE.BODY.roles) || [];
this.body = (info && info.DOCUMENT && info.DOCUMENT.TEMPLATE && info.DOCUMENT.TEMPLATE.BODY) || {};
this.data = (this.body && this.body.roles) || [];
this.actions = [
"terminate",
"terminate-hard",
@ -82,8 +91,92 @@ define(function(require) {
FUNCTION DEFINITIONS
*/
function actionRow(scheduling_action) {
var done_str = scheduling_action.DONE ? (Humanize.prettyTime(scheduling_action.DONE)) : "";
var message_str = scheduling_action.MESSAGE ? scheduling_action.MESSAGE : "";
var action_id = scheduling_action.ID || "";
var update_sched = "";
if(action_id){
update_sched = "<button id='minus_"+scheduling_action.ID+ "' class='small button btn-warning edit_action_x' data_id='"+action_id+"'><i class='fas fa-edit'></i></button>";
}
var str = "<td class='done_row'>" + done_str + "</td>\
<td class='message_row'>" + TemplateUtils.htmlEncode(message_str) + "</td>\
<td colspan='3' style='text-align: right;'>\
<div style='display: flex;justify-content: flex-end;'>\
<div>\
<button id='minus_" + scheduling_action.ID + "' class='small button btn-danger remove_action_x'><i class='fas fa-trash-alt'></i></button>\
</div>\
<div>"+update_sched+"</div>\
</td>\
</tr>";
return str;
}
function actionsTable(parseData) {
var str = "";
var empty = "\
<tr id=\"no_actions_tr\">\
<td colspan=\"6\">" + Locale.tr("No actions to show") + "</td>\
</tr>";
if (!parseData) {
return empty;
} else {
var sched_actions = Array.isArray(parseData)? parseData : [parseData];
if (sched_actions.length <= 0) {
return empty;
}
$.each(sched_actions, function(index, scheduling_action) {
if(scheduling_action && scheduling_action.ID){
var className = "";
var idTD = "<td class=\"id_row\"></td>";
var id = 0;
if(scheduling_action.ID){
className = "_"+scheduling_action.ID;
idTD = "<td class=\"id_row\">" + TemplateUtils.htmlEncode(scheduling_action.ID) + "</td>";
id = scheduling_action.ID;
}
str += "<tr class='tr_action"+className+"' data='" + JSON.stringify(scheduling_action) + "'>";
str += idTD;
var actions = ScheduleActions.fromJSONtoActionsTable([scheduling_action], id, true);
str += actions;
str += actionRow(scheduling_action);
}
});
}
return str;
}
function _htmlSchedActions(vmTemplateContents){
var parseData = TemplateUtils.stringToTemplate(vmTemplateContents);
return "<div class='row'>\
<div class='large-12 columns'>\
<table id='scheduling_"+RESOURCE_SCHED_ACTIONS+"_actions_table' class='info_table dataTable'>\
<thead>\
<tr>\
<th>" + Locale.tr("ID") + "</th>\
<th>" + Locale.tr("Action") + "</th>\
<th>" + Locale.tr("Time") + "</th>\
<th>" + Locale.tr("Rep") + "</th>\
<th>" + Locale.tr("End") + "</th>\
<th>" + Locale.tr("Done") + "</th>\
<th>" + Locale.tr("Message") + "</th>\
<th colspan=''> </th>\
<th><button id='add_scheduling_"+RESOURCE_SCHED_ACTIONS+"_action' class='button small success right radius' >" + Locale.tr("Add action") + "</button></th>\
<th>" +
Leases.html() +
"</th>\
</tr>\
</thead>\
<tbody id='sched_vms_actions_body' class='scheduling_place'>"+
actionsTable(parseData && parseData.SCHED_ACTION) +
"</tbody>\
</table>\
</div>\
</div>";
}
function _html() {
var sched_actions_table = "";
var optionsActions = this.actions.map(function(ac){
return "<option value='"+ac+"'>"+ac+"</option>";
}).join("");
@ -99,43 +192,242 @@ define(function(require) {
optionsRoles.unshift("<option value=''>"+Locale.tr("All Roles")+"</option>");
optionsRoles = optionsRoles.join("");
if(this.data && Array.isArray(this.data) && this.data[0] && this.data[0].vm_template_contents) {
var parseData = TemplateUtils.stringToTemplate(this.data[0].vm_template_contents);
if(parseData && parseData.SCHED_ACTION){
var sched_actions = Array.isArray(parseData.SCHED_ACTION)? parseData.SCHED_ACTION : [parseData.SCHED_ACTION];
sched_actions_table = $("<table/>");
sched_actions.forEach(function(schedAction){
if(schedAction && schedAction.TIME && schedAction.ACTION){
if(schedAction.TIME.startsWith("+")){
time = ScheduleActions.parseTime(schedAction.TIME);
}else{
timeWithMiliSeconds = parseInt(schedAction.TIME,10) * 1000;
timeDate = new Date(timeWithMiliSeconds);
time = "on "+timeDate.getHours()+":"+timeDate.getMinutes()+":"+timeDate.getSeconds()+" "+timeDate.getDate() +"/"+(timeDate.getMonth()+1)+"/"+timeDate.getFullYear();
}
var nameAction = schedAction.ACTION;
sched_actions_table = sched_actions_table.append(
$("<tr/>").append(
$("<td/>").text(nameAction).add(
$("<td/>").text(time)
)
)
);
}
});
sched_actions_table = sched_actions_table.prop("outerHTML");
}
}
return TemplateHTML({
sched_actions_table: sched_actions_table,
sched_actions_table: _htmlSchedActions(this.data[0].vm_template_contents),
actions: optionsActions,
res: RESOURCE,
roles: optionsRoles
});
}
function findMaxID(items) {
return items.reduce((acc, val) => {
acc = ( acc === undefined || val.ID > acc ) ? val.ID : acc;
return acc;
}, 0);
}
function addID(actns){
acc = findMaxID(actns);
return actns.map(el=>{
if(el && !el.ID){
acc = el.ID = parseInt(acc, 10)+1;
}
return el;
});
}
/*** update schedule actions ***/
function updateNodes(that, callback, type = "replace"){
if(callback && typeof callback === "function" && that && that.data){
var roles = Array.isArray(that.data)? that.data : [that.data];
var updateService = true;
roles.forEach(function(element){
if(element && element.vm_template_contents !== undefined && element.nodes){
var jsonTemplateContents = TemplateUtils.stringToTemplate(element.vm_template_contents);
var nodes = Array.isArray(element.nodes)? element.nodes : [element.nodes];
nodes.forEach(element => {
if(element && element.vm_info && element.vm_info.VM && element.vm_info.VM.ID){
OpenNebulaAction.show({
data:{
id: element.vm_info.VM.ID
},
success: function(req, res){
var executedCallback = callback(jsonTemplateContents && jsonTemplateContents.SCHED_ACTION);
var userTemplate = res && res.VM && res.VM.USER_TEMPLATE || {};
var newUserTemplate = {};
switch (type) {
case "add":
var userTemplateSchedActions = userTemplate && userTemplate.SCHED_ACTION || [];
if(userTemplateSchedActions && executedCallback){
var newActions = Array.isArray(userTemplateSchedActions) ? userTemplateSchedActions : [userTemplateSchedActions];
if(Array.isArray(executedCallback)){
newActions = newActions.concat(executedCallback);
}else{
newActions.push(executedCallback);
}
newUserTemplate = addID(newActions);
}
break;
default:
if(executedCallback){
newUserTemplate = addID(executedCallback);
}
break;
}
userTemplate.SCHED_ACTION = newUserTemplate;
//this update the VM
OpenNebulaAction.simple_action(
{
data:{
id: element.vm_info.VM.ID
},
success: function(req){
if(userTemplate && userTemplate.SCHED_ACTION){
$(".sched_place").empty().append(_htmlSchedActions(TemplateUtils.templateToString({SCHED_ACTION: userTemplate.SCHED_ACTION})));
//update service
if(updateService){
updateService = false;
//this set a new vm_template_contents in roles
var rols = that.data.forEach(
function(element){
element.vm_template_contents = TemplateUtils.templateToString({SCHED_ACTION: userTemplate.SCHED_ACTION});
return element;
}
);
Service.update(
{
data:{
id: that.id,
extra_param: JSON.stringify(that.body)
},
success: function(){
updateService = true;
Notifier.notifyCustom(
Locale.tr("Service Updated"),
""
);
},
error: function(req, resp){
updateService = true;
Notifier.notifyError(
(resp && resp.error && resp.error.message) || Locale.tr("Cannot update the Service: ")+(that.id || "")
);
}
}
);
}
}
},
error: function(req, resp){
Notifier.notifyError(
(resp && resp.error && resp.error.message) || Locale.tr("Cannot update the VM: ")+element.vm_info.VM.ID
);
}
},
"VM",
"update",
{
template_raw: TemplateUtils.templateToString(userTemplate)
}
);
},
error: function(){
Notifier.notifyError(Locale.tr("Cannot get information of the VM: ")+element.vm_info.VM.ID);
}
}, "VM");
}
});
}
});
}
}
function functionButtons(context, that, actions){
var CREATE = true;
function clear(){
CREATE = true;
}
function renderCreateForm(){
if(CREATE){
ScheduleActions.htmlNewAction(actions, context, RESOURCE_SCHED_ACTIONS);
ScheduleActions.setup(context);
CREATE = false;
}
return false;
};
//add
context.off("click", "#add_scheduling_"+RESOURCE_SCHED_ACTIONS+"_action").on("click" , "#add_scheduling_"+RESOURCE_SCHED_ACTIONS+"_action", function(e){
e.preventDefault();
renderCreateForm();
$("#edit_"+RESOURCE_SCHED_ACTIONS+"_action_json").hide();
$("#add_"+RESOURCE_SCHED_ACTIONS+"_action_json").show();
});
context.off("click", "#add_"+RESOURCE_SCHED_ACTIONS+"_action_json").on("click" , "#add_"+RESOURCE_SCHED_ACTIONS+"_action_json", function(e) {
e.preventDefault();
var sched_action = ScheduleActions.retrieveNewAction(context);
if (sched_action != false) {
$("#no_actions_tr", context).remove();
$("#sched_vms_actions_body").prepend(ScheduleActions.fromJSONtoActionsTable(sched_action));
}
updateNodes(that, function(){
return sched_action;
},"add");
clear();
});
//update
context.off("click", ".edit_action_x").on("click", ".edit_action_x", function(e) {
e.preventDefault();
var id = $(this).attr("data_id");
if(id && id.length){
renderCreateForm();
$("#edit_"+RESOURCE_SCHED_ACTIONS+"_action_json").show().attr("data_id", id);
$("#add_"+RESOURCE_SCHED_ACTIONS+"_action_json").hide();
ScheduleActions.fill($(this),context);
}
});
context.off("click" , "#edit_"+RESOURCE_SCHED_ACTIONS+"_action_json").on("click" , "#edit_"+RESOURCE_SCHED_ACTIONS+"_action_json", function(e){
e.preventDefault();
var id = $(this).attr("data_id");
if(id && id.length){
$(".wickedpicker").hide();
var sched_action = ScheduleActions.retrieveNewAction(context);
if (sched_action != false) {
var sched_actions = ScheduleActions.retrieve(context);
if(Array.isArray(sched_actions)){
sched_actions = sched_actions.map(
function(action){
if(action && action.ID && action.ID===id){
return sched_action;
}else{
return action;
}
}
);
}
updateNodes(that, function(){
return sched_actions;
},"replace");
}
clear();
}
return false;
});
//delete
context.off("click", ".remove_action_x").on("click", ".remove_action_x", function(e) {
e.preventDefault();
var index = this.id.substring(6, this.id.length);
updateNodes(that, function(schedAction){
var actions = Array.isArray(schedAction)? schedAction : [schedAction];
actions.forEach(function(el, i){
if(el && el.ID && String(el.ID) === index){
delete actions[i];
return;
}
});
return actions;
}, "replace");
clear();
});
}
function _setup(context) {
var that = this;
that.formContext = context;
Leases.actions(that, RESOURCE_SCHED_ACTIONS, "add-service", function(schedActions){
updateNodes(that, function(){
return schedActions;
},"add");
});
var actions = ScheduleActions.defaultActions;
$("select#select_new_action").off("change").on("change",function(){
var snap_name = $("#snapname");
var snap_id = $("#snapid");
@ -185,7 +477,6 @@ define(function(require) {
var snap_name = $("#snapname").val();
var snap_id = $("#snapid").val();
var disk_id = $("#diskid").val();
if(new_action){
var actionJSON = {};
actionJSON.error = function(e){
@ -212,5 +503,6 @@ define(function(require) {
}
return false;
});
functionButtons(context, that, actions);
}
});

View File

@ -83,7 +83,6 @@ define(function(require) {
</table>\
</div>\
</div>";
ScheduleActions.htmlTable(RESOURCE_SCHED_ACTIONS); //only charge the resource attribute
return html;
}
@ -168,8 +167,6 @@ define(function(require) {
that.element.USER_TEMPLATE.SCHED_ACTION = tmp_tmpl;
var template_str = TemplateUtils.templateToString(that.element.USER_TEMPLATE);
// Let OpenNebula know
Sunstone.runAction("VM.update_template", that.element.ID, template_str);
});
context.off("click", ".edit_action_x");

View File

@ -175,6 +175,14 @@ define(function(require) {
);
break;
case "add-service":
var newAction = {
TIME: "+"+(last === 0? startTime.toString() : startTime+last),
ACTION: schedAction
};
newSchedActions.push(newAction);
break;
default:
break;
}
@ -182,6 +190,7 @@ define(function(require) {
pass = true;
}
});
if(type==="submit"){
template.SCHED_ACTION = (
template.SCHED_ACTION?
@ -197,7 +206,7 @@ define(function(require) {
}
if(typeof callback === "function"){
callback();
callback(newSchedActions);
}
if(pass){
@ -237,19 +246,25 @@ define(function(require) {
default:
break;
}
if(resource && action && template){
if(resource && action){
switch (resource.toLowerCase()) {
case "template":
displayAlertCreateLeases("add", template);
break;
case "vm":
if(action.toLowerCase() === "update" && id){
displayAlertCreateLeases("submit", template);
}else{
if(template){
displayAlertCreateLeases("add", template);
}
break;
case "vm":
if(template){
if(action.toLowerCase() === "update" && id){
displayAlertCreateLeases("submit", template);
}else{
displayAlertCreateLeases("add", template);
}
}
break;
case "flow":
displayAlertCreateLeases("add-service");
break;
default:
break;
}

View File

@ -36,9 +36,10 @@ define(function (require) {
'disk-snapshot-delete'
];
function _html(resource, leases = null) {
function _html(resource, leases = null, header = true) {
this.res = resource;
return TemplateTableHTML({
header: header,
res: resource,
leases: leases
});
@ -155,6 +156,9 @@ define(function (require) {
$("#title", context).prop("colspan", "10");
$("#td_days", context).prop("colspan", "8");
}
if (this.res === "flow") {
$("tr.create>td", context).prop("colspan", "8");
}
}
function _setup(context) {
@ -794,7 +798,7 @@ define(function (require) {
str += "<tr class='tr_action' data='" + JSON.stringify(scheduling_action) + "'>";
}
var time = scheduling_action.TIME.toString();
var time = String(scheduling_action.TIME);
time = isNaN(time) ? time_str : (time && time.match(/^\+(.*)/gi) ? _time(time) : time_str);
str += "<td class='action_row'>" + TemplateUtils.htmlEncode(scheduling_action.ACTION) + "</td>\

View File

@ -22,18 +22,20 @@
</style>
<table id="scheduling_{{res}}_actions_table" class="info_table dataTable">
<thead>
<tr>
<th> {{tr "Action"}} </th>
<th> {{tr "Time"}} </th>
<th> {{tr "Rep"}} </th>
<th> {{tr "Ends"}} </th>
<th colspan=""> </th>
<th>
<button id="add_scheduling_{{res}}_action" class="button small success right radius"> {{tr "Add action"}} </button>
</th>
{{#if leases}} <th>{{{leases}}}</th> {{/if}}
</tr>
</thead>
<thead>
{{#if header}}
<tr>
<th> {{tr "Action"}} </th>
<th> {{tr "Time"}} </th>
<th> {{tr "Rep"}} </th>
<th> {{tr "Ends"}} </th>
<th colspan=""> </th>
<th>
<button id="add_scheduling_{{res}}_action" class="button small success right radius"> {{tr "Add action"}} </button>
</th>
{{#if leases}} <th>{{{leases}}}</th> {{/if}}
</tr>
{{/if}}
</thead>
<tbody id="sched_{{res}}_actions_body"></tbody>
</table>