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

Bug #4148: Instantiate shows total cost for VMs, services. Including admin view

This commit is contained in:
Carlos Martín 2016-06-07 18:33:49 +02:00
parent c3122a2ebb
commit fffc798cd0
9 changed files with 202 additions and 91 deletions

View File

@ -16,6 +16,7 @@
define(function(require) {
var OpenNebulaAction = require('./action');
var Config = require('sunstone-config');
var RESOURCE = "VMTEMPLATE";
@ -95,7 +96,56 @@ define(function(require) {
} else {
return true;
}
},
"cost": function(template) {
var cost = 0;
var capacity = template.VMTEMPLATE.TEMPLATE;
var cpuCost = capacity.CPU_COST;
var memoryCost = capacity.MEMORY_COST;
var diskCost = capacity.DISK_COST;
if (cpuCost == undefined){
cpuCost = Config.onedConf.DEFAULT_COST.CPU_COST;
}
if (memoryCost == undefined){
memoryCost = Config.onedConf.DEFAULT_COST.MEMORY_COST;
}
if (diskCost == undefined){
diskCost = Config.onedConf.DEFAULT_COST.DISK_COST;
}
if (capacity.CPU) {
cost += capacity.CPU * cpuCost;
}
if (capacity.MEMORY) {
cost += capacity.MEMORY * memoryCost;
}
if (diskCost != 0) {
var template_disk = capacity.DISK;
var disks = [];
if ($.isArray(template_disk)) {
disks = template_disk;
} else if (!$.isEmptyObject(template_disk)) {
disks = [template_disk];
}
$.each(disks, function(i,disk){
if (disk.SIZE) {
cost += diskCost * disk.SIZE;
}
if (disk.DISK_SNAPSHOT_TOTAL_SIZE) {
cost += diskCost * disk.DISK_SNAPSHOT_TOTAL_SIZE;
}
});
}
return cost;
}
}

View File

@ -29,6 +29,7 @@ define(function(require) {
var Notifier = require('utils/notifier');
var WizardFields = require('utils/wizard-fields');
var UserInputs = require('utils/user-inputs');
var Config = require('sunstone-config');
/*
TEMPLATES
@ -108,6 +109,8 @@ define(function(require) {
that.service_template_json = template_json;
$(".name", context).text(template_json.DOCUMENT.NAME);
$("#instantiate_service_user_inputs", context).empty();
UserInputs.serviceTemplateInsert(
@ -117,6 +120,8 @@ define(function(require) {
n_roles = template_json.DOCUMENT.TEMPLATE.BODY.roles.length;
n_roles_done = 0;
var total_cost = 0;
$.each(template_json.DOCUMENT.TEMPLATE.BODY.roles, function(index, role){
var div_id = "user_input_role_"+index;
@ -127,13 +132,23 @@ define(function(require) {
OpenNebulaTemplate.show({
data : {
id: role.vm_template
id: role.vm_template,
extended: true
},
timeout: true,
success: function (request, vm_template_json){
$("#"+div_id, context).empty();
var cost = OpenNebulaTemplate.cost(vm_template_json);
if (cost != 0 && Config.isFeatureEnabled("showback")) {
total_cost += (cost * role.cardinality);
$(".total_cost_div", context).show();
$(".total_cost_div .cost_value", context).text( (total_cost).toFixed(2) );
}
UserInputs.vmTemplateInsert(
$("#"+div_id, context),
vm_template_json,

View File

@ -28,6 +28,13 @@
<input type="number" min="1" name="service_n_times" id="service_n_times" value="1">
</div>
</div>
<h5>
<span class="name"></span>
<span class="total_cost_div" hidden>
<small class="cost_value">0.00</small>
<small>{{tr "COST"}} / {{tr "HOUR"}}</small>
</span>
</h5>
<div id="instantiate_service_user_inputs">
<i class="fa fa-spinner fa-spin"></i>
</div>

View File

@ -63,7 +63,7 @@ define(function(require) {
ProvisionFlowsList.show(0);
var context = $("#provision_create_flow");
$("#flow_name", context).val('');
//$(".provision_selected_networks").html("");
$(".total_cost_div", context).hide();
$(".provision-pricing-table", context).removeClass("selected");
},
error: Notifier.onError
@ -92,6 +92,7 @@ define(function(require) {
$(".provision_selected_networks").html("");
$(".provision-pricing-table", context).removeClass("selected");
$(".alert-box-error", context).hide();
$(".total_cost_div", context).hide();
$('#provision_vm_instantiate_templates_owner_filter').val('all').change();
$('#provision_vm_instantiate_template_search').val('').trigger('input');
@ -124,63 +125,15 @@ define(function(require) {
'</div>'+
'</fieldset>');
var capacity = template_json.VMTEMPLATE.TEMPLATE;
var cost = 0;
var cost = OpenNebula.Template.cost(template_json);
var cpuCost = capacity.CPU_COST;
var memoryCost = capacity.MEMORY_COST;
var diskCost = capacity.DISK_COST;
if (cpuCost == undefined){
cpuCost = Config.onedConf.DEFAULT_COST.CPU_COST;
}
if (memoryCost == undefined){
memoryCost = Config.onedConf.DEFAULT_COST.MEMORY_COST;
}
if (diskCost == undefined){
diskCost = Config.onedConf.DEFAULT_COST.DISK_COST;
}
if ((cpuCost != 0 || memoryCost != 0 || diskCost != 0) && Config.isFeatureEnabled("showback")) {
if ((cost != 0) && Config.isFeatureEnabled("showback")) {
$(".provision_create_service_cost_div", context).show();
$(".provision_create_service_cost_div", context).data("cost", cost);
if (capacity.CPU) {
cost += capacity.CPU * cpuCost;
$(".cost_value", context).data("CPU_COST", cpuCost);
}
if (capacity.MEMORY) {
cost += capacity.MEMORY * memoryCost;
$(".cost_value", context).data("MEMORY_COST", memoryCost);
}
if (diskCost != 0) {
var template_disk = capacity.DISK;
var disks = [];
if ($.isArray(template_disk)) {
disks = template_disk;
} else if (!$.isEmptyObject(template_disk)) {
disks = [template_disk];
}
$(".cost_value", context).data("DISK_COST", diskCost);
$.each(disks, function(i,disk){
if (disk.SIZE) {
cost += diskCost * disk.SIZE;
}
if (disk.DISK_SNAPSHOT_TOTAL_SIZE) {
cost += diskCost * disk.DISK_SNAPSHOT_TOTAL_SIZE;
}
});
}
$(".provision_create_service_cost_div", context).data("cost", cost)
var cost_value = cost*parseInt(role_template.cardinality);
$(".cost_value", context).html(cost_value.toFixed(2));
_calculateFlowCost();
} else {
$(".provision_create_service_cost_div", context).hide();
}
@ -200,6 +153,7 @@ define(function(require) {
$( ".cardinality_slider_div", context).on("input", 'input', function() {
var cost_value = $(".provision_create_service_cost_div", context).data("cost")*$(this).val();
$(".cost_value", context).html(cost_value.toFixed(2));
_calculateFlowCost();
});
} else {
$( ".cardinality_slider_div", context).hide();
@ -236,7 +190,6 @@ define(function(require) {
CapacityInputs.html() +
'</fieldset>');
CapacityInputs.setup(context);
CapacityInputs.fill(context, element);
@ -283,6 +236,8 @@ define(function(require) {
}
$(".cost_value", context).html(cost.toFixed(2));
_calculateCost();
};
if ((cpuCost != 0 || memoryCost != 0) && Config.isFeatureEnabled("showback")) {
@ -298,6 +253,38 @@ define(function(require) {
}
}
function _calculateCost(){
var context = $("#provision_create_vm");
var capacity_val = parseFloat( $(".provision_create_template_cost_div .cost_value", context).text() );
var disk_val = parseFloat( $(".provision_create_template_disk_cost_div .cost_value", context).text() );
var total = capacity_val + disk_val;
if (total != 0 && Config.isFeatureEnabled("showback")) {
$(".total_cost_div", context).show();
$(".total_cost_div .cost_value", context).text( (total).toFixed(2) );
}
}
function _calculateFlowCost(){
var context = $("#provision_create_flow");
var total = 0;
$.each($(".provision_create_service_cost_div .cost_value", context), function(){
total += parseFloat($(this).text());
});
if (total != 0 && Config.isFeatureEnabled("showback")) {
$(".total_cost_div", context).show();
$(".total_cost_div .cost_value", context).text( (total).toFixed(2) );
}
}
function show_provision_dashboard() {
$(".section_content").hide();
$("#provision_dashboard").fadeIn();
@ -568,7 +555,7 @@ define(function(require) {
$("#provision_create_vm li:not(.is-active) a[href='#provision_dd_template']").trigger("click")
$("#provision_create_vm .total_cost_div").hide();
$("#provision_create_vm .alert-box-error").hide();
$(".section_content").hide();
@ -591,6 +578,7 @@ define(function(require) {
$("li:not(.is-active) a[href='#provision_dd_flow_template']", context).trigger("click")
$(".total_cost_div", context).hide();
$(".alert-box-error", context).hide();
$(".section_content").hide();
@ -897,7 +885,8 @@ define(function(require) {
DisksResize.insert({
template_json: template_json,
disksContext: disksContext,
force_persistent: $(this).prop('checked')
force_persistent: $(this).prop('checked'),
cost_callback: _calculateCost
});
}
});
@ -925,6 +914,8 @@ define(function(require) {
$(".provision_accordion_template .selected_template_logo").html('<i class="fa fa-file-text-o fa-lg"/> ');
}
$("#provision_create_vm .total_cost_div").hide();
$(".provision_accordion_template a").first().trigger("click");
OpenNebula.Template.show({
@ -945,7 +936,8 @@ define(function(require) {
DisksResize.insert({
template_json: template_json,
disksContext: disksContext,
force_persistent: $("input.instantiate_pers", create_vm_context).prop("checked")
force_persistent: $("input.instantiate_pers", create_vm_context).prop("checked"),
cost_callback: _calculateCost
});
} else {
disksContext.html("");
@ -1150,6 +1142,8 @@ define(function(require) {
var data = $(this).data("opennebula");
var body = data.DOCUMENT.TEMPLATE.BODY;
$("#provision_create_flow .total_cost_div").hide();
$(".provision_accordion_flow_template .selected_template").show();
$(".provision_accordion_flow_template .select_template").hide();
$(".provision_accordion_flow_template .selected_template_name").html(TemplateUtils.htmlEncode(data.DOCUMENT.NAME))

View File

@ -16,7 +16,13 @@
<form id="provision_create_flow" class="section_content" hidden>
<div class="row">
<div class="large-12 columns">
<h4>{{tr "Create Service"}}</h4>
<h4>
{{tr "Create Service"}}
<span class="total_cost_div" hidden>
<small class="cost_value">0.00</small>
<small>{{tr "COST"}} / {{tr "HOUR"}}</small>
</span>
</h4>
</div>
</div>
<div class="row">

View File

@ -16,7 +16,13 @@
<form id="provision_create_vm" class="section_content" hidden>
<div class="row">
<div class="large-12 columns">
<h4>{{tr "Create Virtual Machine"}}</h4>
<h4>
{{tr "Create Virtual Machine"}}
<span class="total_cost_div" hidden>
<small class="cost_value">0.00</small>
<small>{{tr "COST"}} / {{tr "HOUR"}}</small>
</span>
</h4>
</div>
</div>
<div class="row">

View File

@ -69,6 +69,7 @@ define(function(require) {
FormPanel.prototype.submitWizard = _submitWizard;
FormPanel.prototype.onShow = _onShow;
FormPanel.prototype.setup = _setup;
FormPanel.prototype.calculateCost = _calculateCost;
return FormPanel;
@ -100,12 +101,28 @@ define(function(require) {
DisksResize.insert({
template_json: template_json,
disksContext: $(".disksContext" + template_json.VMTEMPLATE.ID, context),
force_persistent: persistent
force_persistent: persistent,
cost_callback: that.calculateCost.bind(that)
});
});
});
}
function _calculateCost(){
$.each($(".template-row", this.formContext), function(){
var capacity_val = parseFloat( $(".capacity_cost_div .cost_value", $(this)).text() );
var disk_val = parseFloat( $(".provision_create_template_disk_cost_div .cost_value", $(this)).text() );
var total = capacity_val + disk_val;
if (total != 0 && Config.isFeatureEnabled("showback")) {
$(".total_cost_div", $(this)).show();
$(".total_cost_div .cost_value", $(this)).text( (capacity_val + disk_val).toFixed(2) );
}
});
}
function _submitWizard(context) {
if (!this.selected_nodes || this.selected_nodes.length == 0) {
Notifier.notifyError(Locale.tr("No template selected"));
@ -194,7 +211,8 @@ define(function(require) {
DisksResize.insert({
template_json: template_json,
disksContext: $(".disksContext" + template_json.VMTEMPLATE.ID, context),
force_persistent: $("input.instantiate_pers", context).prop("checked")
force_persistent: $("input.instantiate_pers", context).prop("checked"),
cost_callback: that.calculateCost.bind(that)
});
NicsSection.insert(template_json,
@ -242,6 +260,8 @@ define(function(require) {
}
$(".cost_value", capacityContext).html(cost.toFixed(2));
_calculateCost(context);
});
}

View File

@ -14,32 +14,38 @@
{{! limitations under the License. }}
{{! -------------------------------------------------------------------------- }}
<h6>
{{element.NAME}}
</h6>
<div class="row">
<div class="medium-6 small-12 columns capacityContext{{element.ID}}">
<fieldset>
<legend>
<i class="fa fa-laptop"></i> {{tr "Capacity"}}
<span class="capacity_cost_div" hidden>
<span class="cost_value">0.00</span>
<small>{{tr "COST"}} / {{tr "HOUR"}}</small>
</span>
</legend>
<div>
{{{capacityInputsHTML}}}
</div>
</fieldset>
<div class="template-row" element-id="{{element.ID}}">
<h5>
{{element.NAME}}
<span class="total_cost_div" hidden>
<small class="cost_value">0.00</small>
<small>{{tr "COST"}} / {{tr "HOUR"}}</small>
</span>
</h5>
<div class="row">
<div class="medium-6 small-12 columns capacityContext{{element.ID}}">
<fieldset>
<legend>
<i class="fa fa-laptop"></i> {{tr "Capacity"}}
<span class="capacity_cost_div" hidden>
<span class="cost_value">0.00</span>
<small>{{tr "COST"}} / {{tr "HOUR"}}</small>
</span>
</legend>
<div>
{{{capacityInputsHTML}}}
</div>
</fieldset>
</div>
<div class="medium-6 small-12 columns disksContext{{element.ID}}"></div>
</div>
<div class="medium-6 small-12 columns disksContext{{element.ID}}"></div>
</div>
<div class="row">
<div class="medium-6 small-12 columns template_user_inputs{{element.ID}}"></div>
</div>
<div class="row">
<div class="small-12 columns nicsContext{{element.ID}}">
<div class="provision_network_selector">
<div class="row">
<div class="medium-6 small-12 columns template_user_inputs{{element.ID}}"></div>
</div>
<div class="row">
<div class="small-12 columns nicsContext{{element.ID}}">
<div class="provision_network_selector">
</div>
</div>
</div>
</div>
</div>

View File

@ -28,7 +28,7 @@ define(function(require){
'retrieve': _retrieve
};
function _calculateCost(context, disk_cost){
function _calculateCost(context, disk_cost, callback){
var cost = 0;
$(".diskContainer", context).each(function(){
@ -51,6 +51,10 @@ define(function(require){
});
$(".cost_value", context).text(cost.toFixed(2));
if(callback != undefined){
callback();
}
}
/**
@ -58,6 +62,7 @@ define(function(require){
* - disksContext: jquery selector, where to place the html
* - force_persistent {bool}: mark all disks as if they
* were persistent, disabling resize inputs
* - cost_callback: function to call when the cost changes
*/
function _insert(opts) {
@ -80,14 +85,16 @@ define(function(require){
disk_cost = Config.onedConf.DEFAULT_COST.DISK_COST;
}
disksContext.off("input", "input");
if (disk_cost != 0 && Config.isFeatureEnabled("showback")) {
$(".provision_create_template_disk_cost_div", disksContext).show();
disksContext.on("input", "input", function(){
_calculateCost(disksContext, disk_cost);
_calculateCost(disksContext, disk_cost, opts.cost_callback);
});
_calculateCost(disksContext, disk_cost);
_calculateCost(disksContext, disk_cost, opts.cost_callback);
} else {
$(".provision_create_template_disk_cost_div", disksContext).hide();
}