mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-21 14:50:08 +03:00
Bug #1314: Small sunstone fixes
* Remove hosts view for non-admin users. * Update users main dashboard with user quota information. * Enable users and group plugin for normal users, disabling the administrator operations. * Fix non-working quota edit buttons in Chrome/Safari. Minor dialog improvements. * Add group extended information tab when clicking on a group. * Small fixes regarding disk hotplugging and added labels. * Fix net units in VM monitoring * Fix UNAME not being set correctly when adding images or vnets to templates * Format marketplace images size and add url link to website. * Small corrections here and there.. (cherry picked from commit 2b3019a2e9aa7cfd033c20c67f85bf196c2127c9)
This commit is contained in:
parent
ec8d459589
commit
c1a1cc5813
@ -19,15 +19,13 @@
|
||||
:group:
|
||||
oneadmin: true
|
||||
- plugins/users-tab.js:
|
||||
:ALL: false
|
||||
:ALL: true
|
||||
:user:
|
||||
:group:
|
||||
oneadmin: true
|
||||
- plugins/groups-tab.js:
|
||||
:ALL: false
|
||||
:ALL: true
|
||||
:user:
|
||||
:group:
|
||||
oneadmin: true
|
||||
- plugins/acls-tab.js:
|
||||
:ALL: false
|
||||
:user:
|
||||
@ -59,9 +57,10 @@
|
||||
:group:
|
||||
oneadmin: true
|
||||
- plugins/hosts-tab.js:
|
||||
:ALL: true
|
||||
:ALL: false
|
||||
:user:
|
||||
:group:
|
||||
oneadmin: true
|
||||
- plugins/datastores-tab.js:
|
||||
:ALL: true
|
||||
:user:
|
||||
|
@ -684,4 +684,12 @@ ul.action_list li a:hover{
|
||||
|
||||
div.current_quotas ul{
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.padding1 {
|
||||
padding-left: 30px!important;
|
||||
}
|
||||
|
||||
.padding2 {
|
||||
padding-left: 55px!important;
|
||||
}
|
@ -128,7 +128,7 @@ $(document).ready(function () {
|
||||
applyDefaultStyles: false
|
||||
, center__paneSelector: ".outer-center"
|
||||
, west__paneSelector: ".outer-west"
|
||||
, west__size: 181
|
||||
, west__size: 200
|
||||
, north__size: 26
|
||||
, south__size: 26
|
||||
, spacing_open: 0 // ALL panes
|
||||
|
@ -61,7 +61,10 @@ var cluster_actions = {
|
||||
"Cluster.create" : {
|
||||
type: "create",
|
||||
call : OpenNebula.Cluster.create,
|
||||
callback : addClusterElement,
|
||||
callback : function(){
|
||||
//addClusterElement,
|
||||
Sunstone.runAction('Cluster.list');
|
||||
},
|
||||
error : onError,
|
||||
notify: true
|
||||
},
|
||||
@ -911,7 +914,7 @@ function setupCreateClusterDialog(){
|
||||
}
|
||||
};
|
||||
|
||||
//Create the OpenNebula.Host.
|
||||
//Create the OpenNebula.Cluster.
|
||||
//If it is successfull we refresh the list.
|
||||
Sunstone.runAction("Cluster.create",cluster_json);
|
||||
$create_cluster_dialog.dialog('close');
|
||||
|
@ -14,6 +14,7 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
var config_response;
|
||||
var config_tab_content =
|
||||
'<form>\
|
||||
<table id="config_table" style="width:100%">\
|
||||
@ -81,10 +82,10 @@ Sunstone.addMainTab('config_tab',config_tab);
|
||||
|
||||
// Callback when configuration list is received
|
||||
function updateConfig(request,response){
|
||||
var config = response['user_config'];
|
||||
config_response = response
|
||||
|
||||
//Set wss checkbox to correct value
|
||||
if (config["wss"] == "yes"){
|
||||
if (config_response['user_config']["wss"] == "yes"){
|
||||
$('table#config_table input#wss_checkbox').attr('checked','checked');
|
||||
};
|
||||
};
|
||||
|
@ -190,6 +190,8 @@ var $dashboard;
|
||||
|
||||
// All monitoring calls and config are called from the Sunstone plugins.
|
||||
|
||||
function dashboardQuotasHTML(){}
|
||||
|
||||
$(document).ready(function(){
|
||||
$dashboard = $('#dashboard_tab', main_tabs_context);
|
||||
});
|
@ -22,46 +22,10 @@ var dashboard_tab_content =
|
||||
<tr>\
|
||||
<td>\
|
||||
<div class="panel">\
|
||||
<h3>' + tr("Hosts") + '<i class="icon-refresh action_button" value="Host.refresh" style="float:right;cursor:pointer"></i></h3>\
|
||||
<h3>' + tr("User information") + '</h3>\
|
||||
<div class="panel_info">\
|
||||
<table class="info_table">\
|
||||
<table id="dashboard_user_info" class="info_table">\
|
||||
\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Total Hosts") + '</td>\
|
||||
<td class="key_td">' + tr("State") + '</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td colspan="2"><div id="totalHosts" class="big_text" style="float:left;width:50%;padding-top:12px;"></div>\
|
||||
<div id="statePie" style="float:right;width:50%;height:100px;"></div></td>\
|
||||
</tr>\
|
||||
\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Global CPU Usage") + '</td>\
|
||||
<td></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td colspan="2"><div id="globalCpuUsage" style="width:100%;height:100px;"></div></td>\
|
||||
</tr>\
|
||||
\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Used vs. Max CPU") + '</td>\
|
||||
<td><div id="cpuUsageBar_legend"></div></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td colspan="2">\
|
||||
<div id="cpuUsageBar" style="width:95%;height:50px"></div>\
|
||||
</td>\
|
||||
</tr>\
|
||||
\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Used vs. Max Memory") + '</td>\
|
||||
<td><div id="memoryUsageBar_legend"></div></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td colspan="2">\
|
||||
<div id="memoryUsageBar" style="width:95%;height:50px"></div>\
|
||||
</td>\
|
||||
</tr>\
|
||||
\
|
||||
</table>\
|
||||
\
|
||||
@ -128,8 +92,98 @@ Sunstone.addMainTab('dashboard_tab',dashboard_tab);
|
||||
|
||||
var $dashboard;
|
||||
|
||||
// Monitoring calls and config in Sunstone plugins
|
||||
|
||||
function dashboardQuotaRow(quota_json){
|
||||
var row = '';
|
||||
|
||||
switch (quota_json.TYPE){
|
||||
case "VM":
|
||||
row += '<tr><td class="padding1">'+tr("VMS")+'</td>';
|
||||
row += '<td class="value_td">'+quota_json.VMS_USED+' / '+quota_json.VMS+'</td></tr>';
|
||||
row += '<tr><td class="padding1">'+tr("Memory")+'</td>';
|
||||
row += '<td class="value_td">'+quota_json.MEMORY_USED+' / '+quota_json.MEMORY+'</td></tr>';
|
||||
row += '<tr><td class="padding1">'+tr("CPU")+'</td>';
|
||||
row += '<td class="value_td">'+quota_json.CPU_USED+' / '+quota_json.CPU+'</td></tr>';
|
||||
break;
|
||||
case "DATASTORE":
|
||||
row += '<tr><td class="padding1">'+tr("Datastore")+' id '+quota_json.ID+':</td><td></td></tr>';
|
||||
|
||||
row += '<tr><td class="padding2">'+tr("Size")+'</td>';
|
||||
row += '<td class="value_td">'+quota_json.SIZE_USED+' / '+quota_json.SIZE+'</td>';
|
||||
|
||||
row += '<tr><td class="padding2">'+tr("Images")+'</td>';
|
||||
row += '<td class="value_td">'+quota_json.IMAGES_USED+' / '+quota_json.IMAGES+'</td>';
|
||||
break;
|
||||
case "IMAGE":
|
||||
row += '<tr><td class="padding1">'+tr("Image")+' id '+quota_json.ID+':</td><td></td></tr>';
|
||||
|
||||
row += '<tr><td class="padding2">'+tr("RVMs")+'</td>';
|
||||
row += '<td class="value_td">'+quota_json.RVMS_USED+' / '+quota_json.RVMS+'</td>';
|
||||
break;
|
||||
case "NETWORK":
|
||||
row += '<tr><td class="padding1">'+tr("Network")+' id '+quota_json.ID+':</td><td></td></tr>';
|
||||
|
||||
row += '<tr><td class="padding2">'+tr("Leases")+'</td>';
|
||||
row += '<td class="value_td">'+quota_json.RVMS_USED+' / '+quota_json.RVMS+'</td>';
|
||||
break;
|
||||
}
|
||||
return row
|
||||
}
|
||||
|
||||
function dashboardQuotasHTML(user){
|
||||
var html = '<tr>\
|
||||
<td class="key_td">' + tr("Resource quotas") + '</td>\
|
||||
<td class="value_td">' + tr("Used / Allowed") + '</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td"></td><td class="value_td"></td>\
|
||||
</tr>';
|
||||
|
||||
var results = parseQuotas(user, dashboardQuotaRow);
|
||||
|
||||
html += '<tr><td class="key_td">'+tr("VM quota")+':</td>\
|
||||
<td class="value_td">'+
|
||||
(results.VM.length ? "" : tr("None"))+'</td></tr>'
|
||||
|
||||
html += results.VM;
|
||||
|
||||
html += '<tr>\
|
||||
<td class="key_td"></td><td class="value_td"></td>\
|
||||
</tr>';
|
||||
|
||||
html += '<tr><td class="key_td">'+tr("Datastore quotas")+':</td>\
|
||||
<td class="value_td">'+
|
||||
(results.DATASTORE.length ? "" : tr("None"))+'</td></tr>'
|
||||
|
||||
html += results.DATASTORE;
|
||||
|
||||
html += '<tr>\
|
||||
<td class="key_td"></td><td class="value_td"></td>\
|
||||
</tr>';
|
||||
|
||||
html += '<tr><td class="key_td">'+tr("Image quotas")+':</td>\
|
||||
<td class="value_td">'+
|
||||
(results.IMAGE.length ? "" : tr("None"))+'</td></tr>'
|
||||
|
||||
html += results.IMAGE;
|
||||
|
||||
html += '<tr>\
|
||||
<td class="key_td"></td><td class="value_td"></td>\
|
||||
</tr>';
|
||||
|
||||
html += '<tr><td class="key_td">'+tr("Network quotas")+':</td>\
|
||||
<td class="value_td">'+
|
||||
(results.NETWORK.length ? "" : tr("None"))+'</td></tr>'
|
||||
|
||||
html += results.NETWORK;
|
||||
|
||||
html += '<tr>\
|
||||
<td class="key_td"></td><td class="value_td"></td>\
|
||||
</tr>';
|
||||
|
||||
$('#dashboard_user_info', $dashboard).html(html);
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$dashboard = $('#dashboard_tab', main_tabs_context);
|
||||
$dashboard = $('#dashboard_tab', main_tabs_context);
|
||||
});
|
@ -32,8 +32,8 @@ var groups_tab_content = '\
|
||||
<th>'+tr("Name")+'</th>\
|
||||
<th>'+tr("Users")+'</th>\
|
||||
<th>'+tr("VMs")+'</th>\
|
||||
<th>'+tr("Memory used")+'</th>\
|
||||
<th>'+tr("CPU used")+'</th>\
|
||||
<th>'+tr("Used memory")+'</th>\
|
||||
<th>'+tr("Used CPU")+'</th>\
|
||||
</tr>\
|
||||
</thead>\
|
||||
<tbody id="tbodygroups">\
|
||||
@ -142,10 +142,19 @@ var group_actions = {
|
||||
error: onError,
|
||||
},
|
||||
|
||||
// "Group.showinfo" : {
|
||||
// type: "custom",
|
||||
// call: updateGroupInfo
|
||||
// },
|
||||
"Group.show" : {
|
||||
type: "single",
|
||||
call: OpenNebula.Group.show,
|
||||
callback: updateGroupElement,
|
||||
error: onError
|
||||
},
|
||||
|
||||
"Group.showinfo" : {
|
||||
type: "single",
|
||||
call: OpenNebula.Group.show,
|
||||
callback: updateGroupInfo,
|
||||
error: onError
|
||||
},
|
||||
|
||||
"Group.autorefresh" : {
|
||||
type: "custom",
|
||||
@ -185,7 +194,7 @@ var group_actions = {
|
||||
type: "single",
|
||||
call: OpenNebula.Group.show,
|
||||
callback: function (request,response) {
|
||||
var parsed = parseQuotas(response.GROUP);
|
||||
var parsed = parseQuotas(response.GROUP,quotaListItem);
|
||||
$('.current_quotas table tbody',$group_quotas_dialog).append(parsed.VM);
|
||||
$('.current_quotas table tbody',$group_quotas_dialog).append(parsed.DATASTORE);
|
||||
$('.current_quotas table tbody',$group_quotas_dialog).append(parsed.IMAGE);
|
||||
@ -225,7 +234,8 @@ var group_buttons = {
|
||||
},
|
||||
"Group.create_dialog" : {
|
||||
type: "create_dialog",
|
||||
text: tr("+ New Group")
|
||||
text: tr("+ New Group"),
|
||||
condition: mustBeAdmin
|
||||
},
|
||||
// "Group.chown" : {
|
||||
// type: "confirm_with_select",
|
||||
@ -236,11 +246,13 @@ var group_buttons = {
|
||||
// },
|
||||
"Group.quotas_dialog" : {
|
||||
type : "action",
|
||||
text : tr("Update quotas")
|
||||
text : tr("Update quotas"),
|
||||
condition: mustBeAdmin,
|
||||
},
|
||||
"Group.delete" : {
|
||||
type: "confirm",
|
||||
text: tr("Delete")
|
||||
text: tr("Delete"),
|
||||
condition: mustBeAdmin
|
||||
},
|
||||
"Group.help" : {
|
||||
type: "action",
|
||||
@ -249,17 +261,35 @@ var group_buttons = {
|
||||
}
|
||||
};
|
||||
|
||||
var group_info_panel = {
|
||||
"group_info_tab" : {
|
||||
title: tr("Group information"),
|
||||
content:""
|
||||
},
|
||||
};
|
||||
|
||||
var groups_tab = {
|
||||
title: tr("Groups"),
|
||||
content: groups_tab_content,
|
||||
buttons: group_buttons,
|
||||
tabClass: 'subTab',
|
||||
parentTab: 'system_tab'
|
||||
parentTab: 'system_tab',
|
||||
condition: mustBeAdmin
|
||||
};
|
||||
|
||||
var groups_tab_non_admin = {
|
||||
title: tr("Group info"),
|
||||
content: groups_tab_content,
|
||||
buttons: group_buttons,
|
||||
tabClass: 'subTab',
|
||||
parentTab: 'dashboard_tab',
|
||||
condition: mustNotBeAdmin
|
||||
}
|
||||
|
||||
|
||||
SunstoneMonitoringConfig['GROUP'] = {
|
||||
plot: function(monitoring){
|
||||
if (!mustBeAdmin()) return;
|
||||
$('#totalGroups', $dashboard).text(monitoring['totalGroups'])
|
||||
},
|
||||
monitor: {
|
||||
@ -271,6 +301,8 @@ SunstoneMonitoringConfig['GROUP'] = {
|
||||
|
||||
Sunstone.addActions(group_actions);
|
||||
Sunstone.addMainTab('groups_tab',groups_tab);
|
||||
Sunstone.addMainTab('groups_tab_non_admin',groups_tab_non_admin);
|
||||
Sunstone.addInfoPanel("group_info_panel",group_info_panel);
|
||||
|
||||
function groupElements(){
|
||||
return getSelectedNodes(dataTable_groups);
|
||||
@ -350,9 +382,63 @@ function updateGroupsView(request, group_list){
|
||||
updateView(group_list_array,dataTable_groups);
|
||||
updateGroupSelect(group_list);
|
||||
SunstoneMonitoring.monitor('GROUP', group_list)
|
||||
updateSystemDashboard("groups",group_list);
|
||||
if (mustBeAdmin())
|
||||
updateSystemDashboard("groups",group_list);
|
||||
}
|
||||
|
||||
function updateGroupInfo(request,group){
|
||||
var info = group.GROUP;
|
||||
|
||||
var info_tab_html = '\
|
||||
<table id="info_group_table" class="info_table" style="width:80%">\
|
||||
<thead>\
|
||||
<tr><th colspan="2">' + tr("Group information") + ' - '+info.NAME+'</th></tr>\
|
||||
</thead>\
|
||||
<tbody>\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("ID") + '</td>\
|
||||
<td class="value_td">'+info.ID+'</td>\
|
||||
</tr>\
|
||||
</tbody>\
|
||||
</table>\
|
||||
<table class="info_table" style="width:80%;margin-top:0;margin-bottom:0;">\
|
||||
<thead>\
|
||||
<tr><th colspan="2">' + tr("Quota information") +'</th></tr>\
|
||||
</thead>\
|
||||
<tbody><tr><td class="key_td"></td><td class="value_td"></td></tr></tbody>\
|
||||
</table>';
|
||||
|
||||
if (!$.isEmptyObject(info.VM_QUOTA))
|
||||
info_tab_html += '<table class="info_table" style="width:70%;margin-top:0;margin-left:40px;">\
|
||||
<tbody>'+prettyPrintJSON(info.VM_QUOTA)+'</tbody>\
|
||||
</table>'
|
||||
|
||||
if (!$.isEmptyObject(info.DATASTORE_QUOTA))
|
||||
info_tab_html += '<table class="info_table" style="width:70%;margin-top:0;margin-left:40px;%">\
|
||||
<tbody>'+prettyPrintJSON(info.DATASTORE_QUOTA)+'</tbody>\
|
||||
</table>'
|
||||
|
||||
if (!$.isEmptyObject(info.IMAGE_QUOTA))
|
||||
info_tab_html += '<table class="info_table" style="width:70%;margin-top:0;margin-left:40px;">\
|
||||
<tbody>'+prettyPrintJSON(info.IMAGE_QUOTA)+'</tbody>\
|
||||
</table>';
|
||||
|
||||
if (!$.isEmptyObject(info.NETWORK_QUOTA))
|
||||
info_tab_html += '<table class="info_table" style="width:70%;margin-top:0;margin-left:40px;">\
|
||||
<tbody>'+prettyPrintJSON(info.NETWORK_QUOTA)+'</tbody>\
|
||||
</table>';
|
||||
|
||||
var info_tab = {
|
||||
title : tr("Group information"),
|
||||
content : info_tab_html
|
||||
};
|
||||
|
||||
Sunstone.updateInfoPanelTab("group_info_panel","group_info_tab",info_tab);
|
||||
Sunstone.popUpInfoPanel("group_info_panel");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Prepares the dialog to create
|
||||
function setupCreateGroupDialog(){
|
||||
dialogs_context.append('<div title=\"'+tr("Create group")+'\" id="create_group_dialog"></div>');
|
||||
@ -437,7 +523,8 @@ $(document).ready(function(){
|
||||
|
||||
initCheckAllBoxes(dataTable_groups);
|
||||
tableCheckboxesListener(dataTable_groups);
|
||||
infoListener(dataTable_groups);
|
||||
infoListener(dataTable_groups, 'Group.showinfo');
|
||||
|
||||
$('div#groups_tab div.legend_div').hide();
|
||||
$('div#groups_tab_non_admin div.legend_div').hide();
|
||||
})
|
||||
|
@ -152,6 +152,10 @@ function updateMarketInfo(request,app){
|
||||
<td class="key_td">' + tr("ID") + '</td>\
|
||||
<td class="value_td">'+app['_id']["$oid"]+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("URL") + '</td>\
|
||||
<td class="value_td"><a href="'+config_response.system_config.marketplace_url+'/'+app['_id']["$oid"]+'" target="_blank">'+config_response.system_config.marketplace_url+'/'+app['_id']["$oid"]+'</a></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Publisher") + '</td>\
|
||||
<td class="value_td">'+app['publisher']+'</td>\
|
||||
@ -170,7 +174,7 @@ function updateMarketInfo(request,app){
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Size") + '</td>\
|
||||
<td class="value_td">'+app['files'][0]['size']+'</td>\
|
||||
<td class="value_td">'+humanize_size(app['files'][0]['size'],true)+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("Hypervisor") + '</td>\
|
||||
|
@ -1391,9 +1391,10 @@ function setupCreateTemplateDialog(){
|
||||
|
||||
//Auto-set IMAGE_UNAME hidden field value
|
||||
$('#IMAGE', section_disks).change(function(){
|
||||
var uname = getValue($(this).val(),4,2,dataTable_images);
|
||||
var option = $('option:selected',this);
|
||||
var uname = getValue(option.attr('elem_id'),1,2,dataTable_images);
|
||||
$('input#IMAGE_UNAME',section_disks).val(uname);
|
||||
var target = getValue($(this).val(),4,12,dataTable_images);
|
||||
var target = getValue(option.attr('elem_id'),1,12,dataTable_images);
|
||||
if (target && target != "--")
|
||||
$('input#TARGET',section_disks).val(target);
|
||||
else
|
||||
@ -1555,7 +1556,8 @@ function setupCreateTemplateDialog(){
|
||||
|
||||
//Auto-set IMAGE_UNAME hidden field value
|
||||
$('#NETWORK', section_networks).change(function(){
|
||||
var uname = getValue($(this).val(),4,2,dataTable_vNetworks);
|
||||
var option = $('option:selected',this);
|
||||
var uname = getValue(option.attr('elem_id'),1,2,dataTable_vNetworks);
|
||||
$('input#NETWORK_UNAME',section_networks).val(uname);
|
||||
});
|
||||
|
||||
|
@ -35,8 +35,8 @@ var users_tab_content = '\
|
||||
<th>'+tr("Group")+'</th>\
|
||||
<th>'+tr("Authentication driver")+'</th>\
|
||||
<th>'+tr("VMs")+'</th>\
|
||||
<th>'+tr("Memory used")+'</th>\
|
||||
<th>'+tr("CPU used")+'</th>\
|
||||
<th>'+tr("Used memory")+'</th>\
|
||||
<th>'+tr("Used CPU")+'</th>\
|
||||
<th>'+tr("Group ID")+'</th>\
|
||||
</tr>\
|
||||
</thead>\
|
||||
@ -323,7 +323,7 @@ var user_actions = {
|
||||
// when we receive quotas we parse them and create an
|
||||
// quota objects with html code (<li>) that can be inserted
|
||||
// in the dialog
|
||||
var parsed = parseQuotas(response.USER);
|
||||
var parsed = parseQuotas(response.USER,quotaListItem);
|
||||
$('.current_quotas table tbody',$user_quotas_dialog).append(parsed.VM);
|
||||
$('.current_quotas table tbody',$user_quotas_dialog).append(parsed.DATASTORE);
|
||||
$('.current_quotas table tbody',$user_quotas_dialog).append(parsed.IMAGE);
|
||||
@ -365,7 +365,8 @@ var user_buttons = {
|
||||
},
|
||||
"User.create_dialog" : {
|
||||
type: "create_dialog",
|
||||
text: tr("+ New")
|
||||
text: tr("+ New"),
|
||||
condition: mustBeAdmin
|
||||
},
|
||||
"User.update_dialog" : {
|
||||
type: "action",
|
||||
@ -378,13 +379,15 @@ var user_buttons = {
|
||||
},
|
||||
"User.quotas_dialog" : {
|
||||
type : "action",
|
||||
text : tr("Update quotas")
|
||||
text : tr("Update quotas"),
|
||||
condition: mustBeAdmin
|
||||
},
|
||||
"User.chgrp" : {
|
||||
type: "confirm_with_select",
|
||||
text: tr("Change group"),
|
||||
select: groups_sel,
|
||||
tip: tr("This will change the main group of the selected users. Select the new group")+":"
|
||||
tip: tr("This will change the main group of the selected users. Select the new group")+":",
|
||||
condition: mustBeAdmin
|
||||
},
|
||||
"User.chauth" : {
|
||||
type: "confirm_with_select",
|
||||
@ -396,7 +399,8 @@ var user_buttons = {
|
||||
<option value="x509">'+tr("x509")+'</option>\
|
||||
<option value="public">'+tr("Public")+'</option>'
|
||||
},
|
||||
tip: tr("Please choose the new type of authentication for the selected users")+":"
|
||||
tip: tr("Please choose the new type of authentication for the selected users")+":",
|
||||
condition: mustBeAdmin
|
||||
},
|
||||
// "User.addgroup" : {
|
||||
// type: "confirm_with_select",
|
||||
@ -414,7 +418,8 @@ var user_buttons = {
|
||||
// },
|
||||
"User.delete" : {
|
||||
type: "confirm",
|
||||
text: tr("Delete")
|
||||
text: tr("Delete"),
|
||||
condition: mustBeAdmin
|
||||
},
|
||||
"User.help" : {
|
||||
type: "action",
|
||||
@ -440,12 +445,25 @@ var users_tab = {
|
||||
content: users_tab_content,
|
||||
buttons: user_buttons,
|
||||
tabClass: 'subTab',
|
||||
parentTab: 'system_tab'
|
||||
parentTab: 'system_tab',
|
||||
condition: mustBeAdmin,
|
||||
};
|
||||
|
||||
var users_tab_non_admin = {
|
||||
title: tr("User info"),
|
||||
content: users_tab_content,
|
||||
buttons: user_buttons,
|
||||
tabClass: 'subTab',
|
||||
parentTab: 'dashboard_tab',
|
||||
condition: mustNotBeAdmin,
|
||||
}
|
||||
|
||||
|
||||
SunstoneMonitoringConfig['USER'] = {
|
||||
plot: function(monitoring){
|
||||
//plot only when i am admin
|
||||
if (!mustBeAdmin()) return;
|
||||
|
||||
//plot the number of total users
|
||||
$('#totalUsers', $dashboard).text(monitoring['totalUsers'])
|
||||
|
||||
@ -484,6 +502,7 @@ SunstoneMonitoringConfig['USER'] = {
|
||||
|
||||
Sunstone.addActions(user_actions);
|
||||
Sunstone.addMainTab('users_tab',users_tab);
|
||||
Sunstone.addMainTab('users_tab_non_admin',users_tab_non_admin);
|
||||
Sunstone.addInfoPanel("user_info_panel",user_info_panel);
|
||||
|
||||
function userElements(){
|
||||
@ -553,11 +572,14 @@ function updateUsersView(request,users_list){
|
||||
var user_list_array = [];
|
||||
|
||||
$.each(users_list,function(){
|
||||
if (this.USER.ID == uid)
|
||||
dashboardQuotasHTML(this.USER);
|
||||
user_list_array.push(userElementArray(this));
|
||||
});
|
||||
updateView(user_list_array,dataTable_users);
|
||||
SunstoneMonitoring.monitor('USER', users_list)
|
||||
updateSystemDashboard("users",users_list);
|
||||
if (mustBeAdmin())
|
||||
updateSystemDashboard("users",users_list);
|
||||
updateUserSelect();
|
||||
};
|
||||
|
||||
@ -573,7 +595,7 @@ function updateUserInfo(request,user){
|
||||
</thead>\
|
||||
<tbody>\
|
||||
<tr>\
|
||||
<td class="key_td">' + tr("id") + '</td>\
|
||||
<td class="key_td">' + tr("ID") + '</td>\
|
||||
<td class="value_td">'+user_info.ID+'</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
@ -786,4 +808,5 @@ $(document).ready(function(){
|
||||
infoListener(dataTable_users,'User.showinfo');
|
||||
|
||||
$('div#users_tab div.legend_div').hide();
|
||||
$('div#users_tab_non_admin div.legend_div').hide();
|
||||
});
|
||||
|
@ -38,11 +38,13 @@ var vm_graphs = [
|
||||
{ title : tr("Network transmission"),
|
||||
monitor_resources : "NET_TX",
|
||||
humanize_figures : true,
|
||||
convert_from_bytes : true,
|
||||
history_length : VM_HISTORY_LENGTH
|
||||
},
|
||||
{ title : tr("Network reception"),
|
||||
monitor_resources : "NET_RX",
|
||||
humanize_figures : true,
|
||||
convert_from_bytes : true,
|
||||
history_length : VM_HISTORY_LENGTH
|
||||
}
|
||||
];
|
||||
@ -668,10 +670,10 @@ SunstoneMonitoringConfig['VM'] = {
|
||||
var t = ((new Date().getTime()) - netUsage.time) / 1000 //in secs
|
||||
var bandwidth_up = monitoring['netUsageBar'][1].data[0][0] - netUsage.up
|
||||
bandwidth_up /= t
|
||||
var bandwidth_up_str = humanize_size(bandwidth_up) + "b/s" //bytes /sec
|
||||
var bandwidth_up_str = humanize_size(bandwidth_up,true) + "B/s" //bytes /sec
|
||||
var bandwidth_down = monitoring['netUsageBar'][0].data[0][0] - netUsage.down
|
||||
bandwidth_down /= t
|
||||
var bandwidth_down_str = humanize_size(bandwidth_down) + "b/s" //bytes /sec
|
||||
var bandwidth_down_str = humanize_size(bandwidth_down,true) + "B/s" //bytes /sec
|
||||
|
||||
if (bandwidth_up >= 0)
|
||||
$('#bandwidth_up', $dashboard).text(bandwidth_up_str)
|
||||
@ -742,14 +744,14 @@ SunstoneMonitoringConfig['VM'] = {
|
||||
xaxis: {
|
||||
min: 0,
|
||||
tickFormatter : function(val,axis) {
|
||||
return humanize_size(val);
|
||||
return humanize_size(val,true);
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
noColumns: 3,
|
||||
container: '#netUsageBar_legend',
|
||||
labelFormatter: function(label, series){
|
||||
return label + " - " + humanize_size(series.data[0][0])
|
||||
return label + " - " + humanize_size(series.data[0][0],true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1114,27 +1116,28 @@ function printDisks(vm_info){
|
||||
html += '<tr id="no_disks_tr"><td class="key_td">\
|
||||
'+tr("No disks to show")+'\
|
||||
</td><td class="value_td"></td></tr>';
|
||||
html += '</tbody></table></form>';
|
||||
return html;
|
||||
}
|
||||
else {
|
||||
|
||||
for (var i = 0; i < disks.length; i++){
|
||||
var disk = disks[i];
|
||||
html += '<tr disk_id="'+(disk.DISK_ID)+'"><td class="key_td">';
|
||||
html += disk.DISK_ID + ' - ' +
|
||||
(disk.IMAGE ? disk.IMAGE : "Volatile") + '</td>';
|
||||
html += '<td class="value_td">\
|
||||
for (var i = 0; i < disks.length; i++){
|
||||
var disk = disks[i];
|
||||
html += '<tr disk_id="'+(disk.DISK_ID)+'"><td class="key_td">';
|
||||
html += disk.DISK_ID + ' - ' +
|
||||
(disk.IMAGE ? disk.IMAGE : "Volatile") + '</td>';
|
||||
html += '<td class="value_td">\
|
||||
'+(vm_info.STATE == "3" ? '\
|
||||
<button value="VM.detachdisk" class="detachdisk" style="float:right;color:#555555;height:26px;"><i class="icon-trash icon-large"></i></button>\
|
||||
<button value="VM.detachdisk" class="detachdisk" style="float:right;color:#555555;height:26px;">'+tr("Detach")+' <i class="icon-remove icon-large"></i></button>\
|
||||
' : '')+'\
|
||||
<button value="VM.saveas" class="saveas" style="float:right;margin-right:10px;color:#555555;height:26px;"><i class="icon-download icon-large"></i></button>\
|
||||
<input style="float:right;width:9em;margin-right:10px;margin-top:3px;" type="text" value="saveas_'+vm_info.ID+'_'+disk.DISK_ID+'" name="saveas_name"></input>'
|
||||
+'\
|
||||
</td>';
|
||||
<button value="VM.saveas" class="saveas" style="float:right;margin-right:10px;color:#555555;height:26px;">'+tr("Save")+' <i class="icon-download icon-large"></i></button>\
|
||||
<input style="float:right;width:9em;margin-right:10px;margin-top:3px;" type="text" value="saveas_'+vm_info.ID+'_'+disk.DISK_ID+'" name="saveas_name"></input>\
|
||||
<label style="float:right;margin-top:4px;">'+tr("Save_as name")+':</label>'
|
||||
+'\
|
||||
</td>';
|
||||
}
|
||||
}
|
||||
|
||||
html += '</tbody>\
|
||||
</table>';
|
||||
</table>';
|
||||
|
||||
// If VM is not RUNNING, then we forget about the attach disk form.
|
||||
if (vm_info.STATE != "3"){
|
||||
@ -1163,7 +1166,7 @@ function printDisks(vm_info){
|
||||
</select>\
|
||||
</td>\
|
||||
</tr>\
|
||||
<tr class="at_volatile"><td class="key_td"><label>'+tr("Size")+':</label></td>\
|
||||
<tr class="at_volatile"><td class="key_td"><label>'+tr("Size")+' (MB):</label></td>\
|
||||
<td class="value_td">\
|
||||
<input type="text" name="SIZE" style="width:8em;"></input>\
|
||||
</td>\
|
||||
@ -1186,6 +1189,7 @@ function printDisks(vm_info){
|
||||
<input type="text" name="DEV_PREFIX" value="sd" style="width:8em;"></input>\
|
||||
</td>\
|
||||
</tr>\
|
||||
<!--\
|
||||
<tr class="at_volatile"><td class="key_td"><label>'+tr("Readonly")+':</label></td>\
|
||||
<td class="value_td">\
|
||||
<select name="READONLY" style="width:12em;">\
|
||||
@ -1202,6 +1206,7 @@ function printDisks(vm_info){
|
||||
</select>\
|
||||
</td>\
|
||||
</tr>\
|
||||
-->\
|
||||
<tr><td class="key_td"></td>\
|
||||
<td class="value_td">\
|
||||
<button type="submit" value="VM.attachdisk">Attach</button>\
|
||||
@ -1282,8 +1287,8 @@ function hotpluggingOps(){
|
||||
disk_obj.FORMAT = $('input[name="FORMAT"]',this).val();
|
||||
disk_obj.TYPE = $('select[name="TYPE"]',this).val();
|
||||
disk_obj.DEV_PREFIX = $('input[name="DEV_PREFIX"]',this).val();
|
||||
disk_obj.READONLY = $('select[name="READONLY"]',this).val();
|
||||
disk_obj.SAVE = $('save[name="SAVE"]',this).val();
|
||||
// disk_obj.READONLY = $('select[name="READONLY"]',this).val();
|
||||
// disk_obj.SAVE = $('save[name="SAVE"]',this).val();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -76,11 +76,13 @@ function pretty_time_runtime(time){
|
||||
}
|
||||
|
||||
//returns a human readable size in Kilo, Mega, Giga or Tera bytes
|
||||
function humanize_size(value) {
|
||||
//if no from_bytes, assumes value comes in Ks
|
||||
function humanize_size(value,from_bytes) {
|
||||
if (typeof(value) === "undefined") {
|
||||
value = 0;
|
||||
}
|
||||
var binarySufix = ["K", "M", "G", "T" ];
|
||||
var binarySufix = from_bytes ?
|
||||
["", "K", "M", "G", "T" ] : ["K", "M", "G", "T" ];
|
||||
var i=0;
|
||||
while (value > 1024 && i < 3){
|
||||
value = value / 1024;
|
||||
@ -561,12 +563,18 @@ function getSelectedNodes(dataTable){
|
||||
return selected_nodes;
|
||||
}
|
||||
|
||||
//returns a HTML string with a select input code generated from
|
||||
//a dataTable. Allows filtering elements.
|
||||
//returns a HTML string with options for
|
||||
//a select input code generated from a dataTable.
|
||||
//Allows filtering elements specifing status columns
|
||||
//and bad status (if the values of the columns match the bad status)
|
||||
//then this elem is skipped.
|
||||
//no_empty_obj allows to skip adding a Please Select option
|
||||
function makeSelectOptions(dataTable,
|
||||
id_col,name_col,
|
||||
option_value_col,
|
||||
option_name_col,
|
||||
status_cols,
|
||||
bad_status_values,no_empty_opt){
|
||||
bad_status_values,
|
||||
no_empty_opt){
|
||||
var nodes = dataTable.fnGetData();
|
||||
var select = "";
|
||||
if (!no_empty_opt)
|
||||
@ -574,8 +582,12 @@ function makeSelectOptions(dataTable,
|
||||
var array;
|
||||
for (var j=0; j<nodes.length;j++){
|
||||
var elem = nodes[j];
|
||||
var id = elem[id_col];
|
||||
var name = elem[name_col];
|
||||
var value = elem[option_value_col];
|
||||
|
||||
//ASSUMPTION: elem id in column 1
|
||||
var id = elem[1];
|
||||
|
||||
var name = elem[option_name_col];
|
||||
var status, bad_status;
|
||||
var ok=true;
|
||||
for (var i=0;i<status_cols.length;i++){
|
||||
@ -589,7 +601,7 @@ function makeSelectOptions(dataTable,
|
||||
};
|
||||
};
|
||||
if (ok){
|
||||
select +='<option value="'+id+'">'+name+'</option>';
|
||||
select +='<option elem_id="'+id+'" value="'+value+'">'+name+' (id:'+id+')</option>';
|
||||
};
|
||||
};
|
||||
return select;
|
||||
@ -607,9 +619,9 @@ function escapeDoubleQuotes(string){
|
||||
//of plotting comes, we can put the data in the right place.
|
||||
function generateMonitoringDivs(graphs, id_prefix){
|
||||
var str = "";
|
||||
//43% of the width of the screen minus
|
||||
//40% of the width of the screen minus
|
||||
//181px (left menu size)
|
||||
var width = ($(window).width()-181)*40/100;
|
||||
var width = ($(window).width()-200)*39/100;
|
||||
var id_suffix="";
|
||||
var label="";
|
||||
var id="";
|
||||
@ -640,6 +652,7 @@ function plot_graph(data,context,id_prefix,info){
|
||||
var labels = info.monitor_resources;
|
||||
var humanize = info.humanize_figures ?
|
||||
humanize_size : function(val){ return val };
|
||||
var convert_from_bytes = info.convert_from_bytes;
|
||||
var id_suffix = labels.replace(/,/g,'_');
|
||||
id_suffix = id_suffix.replace(/\//g,'_');
|
||||
var labels_array = labels.split(',');
|
||||
@ -652,7 +665,8 @@ function plot_graph(data,context,id_prefix,info){
|
||||
//labels array.
|
||||
for (var i=0; i<labels_array.length; i++) {
|
||||
serie = {
|
||||
label: labels_array[i],
|
||||
//Turns label TEMPLATE/BLABLA into BLABLA
|
||||
label: labels_array[i].split('/').pop(),
|
||||
data: monitoring[labels_array[i]]
|
||||
};
|
||||
series.push(serie);
|
||||
@ -664,7 +678,7 @@ function plot_graph(data,context,id_prefix,info){
|
||||
// * Axis options: print time and sizes correctly
|
||||
var options = {
|
||||
legend : { show : true,
|
||||
noColumns: mon_count++,
|
||||
noColumns: mon_count+1,
|
||||
container: $('#legend_'+id_suffix)
|
||||
},
|
||||
xaxis : {
|
||||
@ -674,7 +688,7 @@ function plot_graph(data,context,id_prefix,info){
|
||||
},
|
||||
yaxis : { labelWidth: 40,
|
||||
tickFormatter: function(val, axis) {
|
||||
return humanize(val);
|
||||
return humanize(val, convert_from_bytes);
|
||||
},
|
||||
min: 0
|
||||
}
|
||||
@ -835,6 +849,10 @@ function mustBeAdmin(){
|
||||
return gid == 0;
|
||||
}
|
||||
|
||||
function mustNotBeAdmin(){
|
||||
return !mustBeAdmin();
|
||||
}
|
||||
|
||||
function users_sel(){
|
||||
return users_select;
|
||||
}
|
||||
@ -1008,6 +1026,13 @@ function setupQuotasDialog(dialog){
|
||||
|
||||
json['TYPE'] = sel.toUpperCase();
|
||||
|
||||
if (json['TYPE'] == "VM" &&
|
||||
$('.current_quotas table tbody tr.vm_quota', dialog).length){
|
||||
notifyError("Only 1 VM quota is allowed")
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var tr = quotaListItem(json)
|
||||
$('.current_quotas table tbody',dialog).append($(tr).hide().fadeIn());
|
||||
return false;
|
||||
@ -1081,7 +1106,7 @@ function setupQuotaIcons(){
|
||||
}
|
||||
|
||||
// Returns an object with quota information in form of list items
|
||||
function parseQuotas(elem){
|
||||
function parseQuotas(elem, formatter_f){
|
||||
var quotas = [];
|
||||
var results = {
|
||||
VM : "",
|
||||
@ -1132,7 +1157,7 @@ function parseQuotas(elem){
|
||||
}
|
||||
|
||||
for (var i = 0; i < quotas.length; i++){
|
||||
var tr = quotaListItem(quotas[i]);
|
||||
var tr = formatter_f(quotas[i]);
|
||||
results[quotas[i].TYPE] += tr;
|
||||
}
|
||||
return results;
|
||||
@ -1141,29 +1166,34 @@ function parseQuotas(elem){
|
||||
//Receives a quota json object. Returns a nice string out of it.
|
||||
function quotaListItem(quota_json){
|
||||
var value = JSON.stringify(quota_json)
|
||||
var str = '<tr quota=\''+value+'\'><td>'+
|
||||
var str = '<tr quota=\''+value+'\' ';
|
||||
|
||||
if (quota_json.TYPE == "VM")
|
||||
str += ' class="vm_quota" ';
|
||||
|
||||
str += '><td>'+
|
||||
quota_json.TYPE+
|
||||
'</td><td style="width:100%;"><pre style="margin:0;">';
|
||||
switch(quota_json.TYPE){
|
||||
case "VM":
|
||||
str += 'VMs: ' + quota_json.VMS + (quota_json.VMS_USED ? ' (' + quota_json.VMS_USED + '). ' : ". ") +
|
||||
'Memory: ' + quota_json.MEMORY + (quota_json.MEMORY_USED ? ' (' + quota_json.MEMORY_USED + '). ' : ". ") +
|
||||
'Memory: ' + quota_json.MEMORY + (quota_json.MEMORY_USED ? 'MB (' + quota_json.MEMORY_USED + 'MB). ' : ". ") +
|
||||
'CPU: ' + quota_json.CPU + (quota_json.CPU_USED ? ' (' + quota_json.CPU_USED + '). ' : ". ");
|
||||
break;
|
||||
case "DATASTORE":
|
||||
str += 'ID: ' + getDatastoreName(quota_json.ID) + '. ' +
|
||||
'Size: ' + quota_json.SIZE + (quota_json.SIZE_USED ? ' (' + quota_json.SIZE_USED + '). ' : ". ") +
|
||||
str += 'ID/Name: ' + getDatastoreName(quota_json.ID) + '. ' +
|
||||
'Size: ' + quota_json.SIZE + (quota_json.SIZE_USED ? 'MB (' + quota_json.SIZE_USED + 'MB). ' : ". ") +
|
||||
'Images: ' + quota_json.IMAGES + (quota_json.IMAGES_USED ? ' (' + quota_json.IMAGES_USED + '). ' : ".");
|
||||
break;
|
||||
case "IMAGE":
|
||||
str += 'ID: ' + getImageName(quota_json.ID) + '. ' +
|
||||
str += 'ID/Name: ' + getImageName(quota_json.ID) + '. ' +
|
||||
'RVMs: ' + quota_json.RVMS + (quota_json.RVMS_USED ? ' (' + quota_json.RVMS_USED + '). ' : ". ");
|
||||
break;
|
||||
case "NETWORK":
|
||||
str += 'ID: ' + getVNetName(quota_json.ID) + '. ' +
|
||||
str += 'ID/Name: ' + getVNetName(quota_json.ID) + '. ' +
|
||||
'Leases: ' + quota_json.LEASES + (quota_json.LEASES_USED ? ' (' + quota_json.LEASES_USED + '). ': ". ");
|
||||
break;
|
||||
}
|
||||
str += '</td><td><i class="quota_edit_icon icon-pencil"></i></pre></td></tr>';
|
||||
str += '</td><td><button class="quota_edit_icon"><i class="icon-pencil"></i></button></pre></td></tr>';
|
||||
return str;
|
||||
}
|
@ -255,7 +255,11 @@ get '/config' do
|
||||
uconf = {
|
||||
:user_config => {
|
||||
:lang => session[:lang],
|
||||
:wss => session[:wss]
|
||||
:wss => session[:wss],
|
||||
:marketplace_url => settings.config[:marketplace_url]
|
||||
},
|
||||
:system_config => {
|
||||
:marketplace_url => settings.config[:marketplace_url]
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user