').click(function () {
+ // Do not load panel again if it is already loaded
+ if ($('#zvmNetworkResource').children().length)
+ return;
+ else
+ $('#zvmNetworkResource').append(createLoader(''));
+
+ // Resize accordion
+ $('#zvmResourceAccordion').accordion('resize');
+
+ // Create a array for hardware control points
+ var hcps = new Array();
+ if ($.cookie('hcp').indexOf(',') > -1)
+ hcps = $.cookie('hcp').split(',');
+ else
+ hcps.push($.cookie('hcp'));
+
+ for ( var i in hcps) {
+ // Gather networks from hardware control points
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsvm',
+ tgt : hcps[i],
+ args : '--getnetworknames',
+ msg : hcps[i]
+ },
+
+ success : getNetwork
+ });
+ }
+ });
+
+ resourcesAccordion.append(diskLnk, diskSection, networkLnk, networkSection);
+
+ // Append accordion to tab
+ $('#' + tabId).append(resourcesAccordion);
+ resourcesAccordion.accordion();
+ diskLnk.trigger('click');
}
}
@@ -1785,48 +1841,39 @@ function getNetwork(data) {
* @return Nothing
*/
function loadDiskPoolTable(data) {
+ // Remove loader
+ var panelId = 'zvmDiskResource';
+ $('#' + panelId).find('img[src="images/loader.gif"]').remove();
+
var args = data.msg.split(';');
var hcp = args[0].replace('hcp=', '');
var pool = args[1].replace('pool=', '');
var stat = args[2].replace('stat=', '');
var tmp = data.rsp[0].split(hcp + ': ');
- // Remove loader
- var loaderId = 'zvmResourceLoader';
- if ($('#' + loaderId).length) {
- $('#' + loaderId).remove();
- }
-
- // Resource tab ID
- var tabID = 'zvmResourceTab';
- var info = $('#' + tabID).find('.ui-state-highlight');
+ // Resource tab ID
+ var info = $('#' + panelId).find('.ui-state-highlight');
// If there is no info bar
if (!info.length) {
// Create info bar
- info = createInfoBar('Below are disks and networks found by the hardware control point. It shows disk pools defined in the EXTENT CONTROL file and LANs|VSWITCHes available to use.');
- $('#' + tabID).append(info);
+ info = createInfoBar('Below are disks that are defined in the EXTENT CONTROL file.');
+ $('#' + panelId).append(info);
}
// Get datatable
+ var tableId = 'zDiskDataTable';
var dTable = getDiskDataTable();
if (!dTable) {
- // Create disks section
- var fieldSet = $('');
- var legend = $('');
- fieldSet.append(legend);
-
- // Create a datatable
- var tableID = 'zDiskDataTable';
- var table = new DataTable(tableID);
+ // Create a datatable
+ var table = new DataTable(tableId);
// Resource headers: volume ID, device type, start address, and size
- table.init( [ 'HCP', 'Pool', 'Status', 'Volume ID', 'Device type', 'Start address', 'Size' ]);
+ table.init( [ '', 'HCP', 'Pool', 'Status', 'Region', 'Device type', 'Starting address', 'Size' ]);
- // Append datatable to tab
- fieldSet.append(table.object());
- $('#' + tabID).append(fieldSet);
+ // Append datatable to panel
+ $('#' + panelId).append(table.object());
// Turn into datatable
- dTable = $('#' + tableID).dataTable();
+ dTable = $('#' + tableId).dataTable();
setDiskDataTable(dTable);
}
@@ -1834,8 +1881,371 @@ function loadDiskPoolTable(data) {
for ( var i = 2; i < tmp.length; i++) {
tmp[i] = jQuery.trim(tmp[i]);
var diskAttrs = tmp[i].split(' ');
- dTable.fnAddData( [ hcp, pool, stat, diskAttrs[0], diskAttrs[1], diskAttrs[2], diskAttrs[3] ]);
+ dTable.fnAddData( [ '', hcp, pool, stat, diskAttrs[0], diskAttrs[1], diskAttrs[2], diskAttrs[3] ]);
}
+
+ // Create actions menu
+ if (!$('#zvmResourceActions').length) {
+ // Empty filter area
+ $('#' + tableId + '_length').empty();
+
+ // Add disk to pool
+ var addLnk = $('Add');
+ addLnk.bind('click', function(event){
+ openAddDisk2PoolDialog();
+ });
+
+ // Delete disk from pool
+ var deleteLnk = $('Delete');
+ deleteLnk.bind('click', function(event){
+ openDeleteDiskFromPoolDialog();
+ });
+
+ // Refresh table
+ var refreshLnk = $('Refresh');
+ refreshLnk.bind('click', function(event){
+
+ });
+
+ // Create action bar
+ var actionBar = $('');
+
+ // Create an action menu
+ var actionsMenu = createMenu([addLnk, deleteLnk, refreshLnk]);
+ actionsMenu.superfish();
+ actionsMenu.css('display', 'inline-block');
+ actionBar.append(actionsMenu);
+
+ // Set correct theme for action menu
+ actionsMenu.find('li').hover(function() {
+ setMenu2Theme($(this));
+ }, function() {
+ setMenu2Normal($(this));
+ });
+
+ // Create a division to hold actions menu
+ var menuDiv = $('');
+ $('#' + tableId + '_length').prepend(menuDiv);
+ $('#' + tableId + '_length').css({
+ 'padding': '0px',
+ 'width': '500px'
+ });
+ $('#' + tableId + '_filter').css({'padding': '10px',});
+ menuDiv.append(actionBar);
+ }
+
+ /**
+ * Enable editable columns
+ */
+ // Do not make 1st, 2nd, 4th, 5th, 6th, 7th, or 8th column editable
+ $('#' + tableId + ' td:not(td:nth-child(1),td:nth-child(2),td:nth-child(4),td:nth-child(5),td:nth-child(6),td:nth-child(7),td:nth-child(8))').editable(
+ function(value, settings) {
+ // If users did not make changes, return the value directly
+ // jeditable saves the old value in this.revert
+ if ($(this).attr('revert') == value){
+ return value;
+ }
+
+ // Get column index
+ var colPos = this.cellIndex;
+
+ // Get row index
+ var dTable = $('#' + tableId).dataTable();
+ var rowPos = dTable.fnGetPosition(this.parentNode);
+
+ // Update datatable
+ dTable.fnUpdate(value, rowPos, colPos, false);
+
+ // Get table headers
+ var headers = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
+
+ // Get node name
+ var node = $(this).parent().find('td a.node').text();
+ // Get attribute name
+ var attrName = jQuery.trim(headers.eq(colPos).text());
+ // Get column value
+ var value = $(this).text();
+
+ // Build argument
+ var args = attrName + '=' + value;
+
+ // Send command to change node attributes
+// $.ajax( {
+// url : 'lib/cmd.php',
+// dataType : 'json',
+// data : {
+// cmd : 'chdef',
+// tgt : '',
+// args : '-t;node;-o;' + node + ';' + args,
+// msg : 'out=nodesTab;tgt=' + node
+// },
+//
+// success: showChdefOutput
+// });
+
+ return value;
+ }, {
+ onblur : 'submit', // Clicking outside editable area submits changes
+ type : 'textarea',
+ placeholder: ' ',
+ event : "dblclick", // Double click and edit
+ height : '50px' // The height of the text area
+ });
+
+ // Resize accordion
+ $('#zvmResourceAccordion').accordion('resize');
+}
+
+/**
+ * Open dialog to delete disk from pool
+ */
+function openDeleteDiskFromPoolDialog() {
+ // Create form to delete disk to pool
+ var dialogId = 'zvmDeleteDiskFromPool';
+ var deleteDiskForm = $('');
+ // Create info bar
+ var info = createInfoBar('Remove a disk from a disk pool defined in the EXTENT CONTROL.');
+ deleteDiskForm.append(info);
+ var action = $('');
+ var actionSelect = $('');
+ action.append(actionSelect);
+
+ var hcp = $('');
+ var hcpSelect = $('');
+ hcp.append(hcpSelect);
+ var region = $('');
+ var group = $('');
+ deleteDiskForm.append(action, hcp, region, group);
+
+ // Create a array for hardware control points
+ var hcps = new Array();
+ if ($.cookie('hcp').indexOf(',') > -1)
+ hcps = $.cookie('hcp').split(',');
+ else
+ hcps.push($.cookie('hcp'));
+
+ // Append options for hardware control points
+ for (var i in hcps) {
+ hcpSelect.append($(''));
+ }
+
+ actionSelect.change(function() {
+ if ($(this).val() == '1' || $(this).val() == '3') {
+ region.show();
+ group.hide();
+ } else if ($(this).val() == '2') {
+ region.show();
+ group.show();
+ } else if ($(this).val() == '7') {
+ region.val('FOOBAR');
+ region.hide();
+ group.show();
+ }
+ });
+
+ // Open dialog to delete disk
+ deleteDiskForm.dialog({
+ title:'Delete disk from pool',
+ modal: true,
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ // Remove any warning messages
+ $(this).find('.ui-state-error').remove();
+
+ // Get inputs
+ var action = $(this).find('select[name=action]').val();
+ var hcp = $(this).find('select[name=hcp]').val();
+ var region = $(this).find('input[name=region]').val();
+ var group = $(this).find('input[name=group]').val();
+
+ // If inputs are not complete, show warning message
+ if (!action || !hcp) {
+ var warn = createWarnBar('Please provide a value for each missing field.');
+ warn.prependTo($(this));
+ } else {
+ // Change dialog buttons
+ $(this).dialog('option', 'buttons', {
+ 'Close': function() {$(this).dialog("close");}
+ });
+
+ var args;
+ if (action == '2' || action == '7')
+ args = region + ';' + group;
+ else
+ args = group;
+
+ // Add disk to pool
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'chvm',
+ tgt : hcp,
+ args : '--removediskfrompool;' + action + ';' + args,
+ msg : dialogId
+ },
+
+ success : updateResourceDialog
+ });
+ }
+ },
+ "Cancel": function() {
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Open dialog to add disk to pool
+ */
+function openAddDisk2PoolDialog() {
+ // Create form to add disk to pool
+ var dialogId = 'zvmAddDisk2Pool';
+ var addDiskForm = $('');
+ // Create info bar
+ var info = createInfoBar('Add a disk to a disk pool defined in the EXTENT CONTROL. The disk has to already be attached to SYSTEM.');
+ addDiskForm.append(info);
+ var action = $('');
+ var actionSelect = $('');
+ action.append(actionSelect);
+
+ var hcp = $('');
+ var hcpSelect = $('');
+ hcp.append(hcpSelect);
+ var region = $('');
+ var volume = $('');
+ var group = $('');
+ addDiskForm.append(action, hcp, region, volume, group);
+
+ // Create a array for hardware control points
+ var hcps = new Array();
+ if ($.cookie('hcp').indexOf(',') > -1)
+ hcps = $.cookie('hcp').split(',');
+ else
+ hcps.push($.cookie('hcp'));
+
+ // Append options for hardware control points
+ for (var i in hcps) {
+ hcpSelect.append($(''));
+ }
+
+ actionSelect.change(function() {
+ if ($(this).val() == '4') {
+ volume.show();
+ } else if ($(this).val() == '5') {
+ volume.hide();
+ }
+ });
+
+ // Open dialog to add disk
+ addDiskForm.dialog({
+ title:'Add disk to pool',
+ modal: true,
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ // Remove any warning messages
+ $(this).find('.ui-state-error').remove();
+
+ // Get inputs
+ var action = $(this).find('select[name=action]').val();
+ var hcp = $(this).find('select[name=hcp]').val();
+ var region = $(this).find('input[name=region]').val();
+ var volume = $(this).find('input[name=volume]').val();
+ var group = $(this).find('input[name=group]').val();
+
+ // If inputs are not complete, show warning message
+ if (!action || !hcp || !region || !group) {
+ var warn = createWarnBar('Please provide a value for each missing field.');
+ warn.prependTo($(this));
+ } else {
+ // Change dialog buttons
+ $(this).dialog('option', 'buttons', {
+ 'Close': function() {$(this).dialog("close");}
+ });
+
+ var args;
+ if (action == '4')
+ args = region + ';' + volume + ';' + group;
+ else
+ args = region + ';' + group;
+
+ // Add disk to pool
+ $.ajax( {
+ url : 'lib/cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'chvm',
+ tgt : hcp,
+ args : '--adddisk2pool;' + action + ';' + args,
+ msg : dialogId
+ },
+
+ success : updateResourceDialog
+ });
+ }
+ },
+ "Cancel": function() {
+ $(this).dialog( "close" );
+ }
+ }
+ });
+}
+
+/**
+ * Update resource dialog
+ *
+ * @param data
+ * HTTP request data
+ * @return Nothing
+ */
+function updateResourceDialog(data) {
+ var dialogId = data.msg;
+ var infoMsg;
+
+ // Create info message
+ if (jQuery.isArray(data.rsp)) {
+ infoMsg = '';
+ for (var i in data.rsp) {
+ infoMsg += data.rsp[i] + '';
+ }
+ } else {
+ infoMsg = data.rsp;
+ }
+
+ // Append info to dialog
+ var info = createInfoBar(infoMsg);
+ info.prependTo($('#' + dialogId));
+}
+
+/**
+ * Select all checkboxes in the datatable
+ *
+ * @param event
+ * Event on element
+ * @param obj
+ * Object triggering event
+ * @return Nothing
+ */
+function selectAllDisk(event, obj) {
+ // Get datatable ID
+ // This will ascend from
+ var tableObj = obj.parents('.datatable');
+ var status = obj.attr('checked');
+ tableObj.find(' :checkbox').attr('checked', status);
+ event.stopPropagation();
}
/**
@@ -1846,44 +2256,35 @@ function loadDiskPoolTable(data) {
* @return Nothing
*/
function loadNetworkTable(data) {
+ // Remove loader
+ var panelId = 'zvmNetworkResource';
+ $('#' + panelId).find('img[src="images/loader.gif"]').remove();
+
var args = data.msg.split(';');
var hcp = args[0].replace('hcp=', '');
var type = args[1].replace('type=', '');
var name = args[2].replace('network=', '');
var tmp = data.rsp[0].split(hcp + ': ');
- // Remove loader
- var loaderId = 'zvmResourceLoader';
- if ($('#' + loaderId).length) {
- $('#' + loaderId).remove();
- }
-
- // Resource tab ID
- var tabId = 'zvmResourceTab';
- var info = $('#' + tabId).find('.ui-state-highlight');
+ // Resource tab ID
+ var info = $('#' + panelId).find('.ui-state-highlight');
// If there is no info bar
if (!info.length) {
// Create info bar
- info = createInfoBar('Below are disks and networks found by the hardware control point. It shows disk pools defined in the EXTENT CONTROL file and LANs|VSWITCHes available to use.');
- $('#' + tabId).append(info);
+ info = createInfoBar('Below are LANs/VSWITCHes available to use.');
+ $('#' + panelId).append(info);
}
// Get datatable
var dTable = getNetworkDataTable();
- if (!dTable) {
- // Create networks section
- var fieldSet = $('');
- var legend = $('');
- fieldSet.append(legend);
-
+ if (!dTable) {
// Create table
var tableId = 'zNetworkDataTable';
var table = new DataTable(tableId);
table.init( [ 'HCP', 'Type', 'Name', 'Details' ]);
// Append datatable to tab
- fieldSet.append(table.object());
- $('#' + tabId).append(fieldSet);
+ $('#' + panelId).append(table.object());
// Turn into datatable
dTable = $('#' + tableId).dataTable();
@@ -1904,7 +2305,10 @@ function loadNetworkTable(data) {
}
details += '';
- dTable.fnAddData( [ hcp, type, name, details ]);
+ dTable.fnAddData([ '
' + hcp + '
', '
' + type + '
', '
' + name + '
', details ]);
+
+ // Resize accordion
+ $('#zvmResourceAccordion').accordion('resize');
}
/**
diff --git a/xCAT-UI/js/service/service.js b/xCAT-UI/js/service/service.js
index b7c35e970..0a71e82da 100644
--- a/xCAT-UI/js/service/service.js
+++ b/xCAT-UI/js/service/service.js
@@ -138,7 +138,7 @@ function loadServicePage() {
}
});
}
-
+
// Get contents of hosts table
if (!$.cookie('srv_groups')) {
$.ajax( {
@@ -156,6 +156,48 @@ function loadServicePage() {
}
});
}
+
+ // Check if user has root privilege
+ // If so, add an admin tab
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'getuserprivilege;' + $.cookie('xcat_username'),
+ msg : ''
+ },
+
+ success : function(data) {
+ var rsp = jQuery.trim(data.rsp);
+ rsp = rsp.replace('Privilege:', '');
+ var privilege = jQuery.trim(rsp);
+
+ // If the user has root privilege, create an administrator tab
+ if (privilege == 'root') {
+ var configTabId = 'configTab';
+ serviceTabs.add(configTabId, 'Configure', '', false);
+ loadConfigPage(configTabId);
+ }
+ }
+ });
+}
+
+/**
+ * Load the service portal's configure page
+ *
+ * @param tabId
+ * Tab ID where page will reside
+ * @return Nothing
+ */
+function loadConfigPage(tabId) {
+ // Create info bar
+ var infoBar = createInfoBar('Select a platform to configure, then click Ok.');
+
+ // Create configure page
+ var configPg = $('');
+ $('#' + tabId).append(infoBar, configPg);
}
/**
diff --git a/xCAT-UI/xcat/plugins/webportal.pm b/xCAT-UI/xcat/plugins/webportal.pm
index 54b96636f..16c1f8b90 100644
--- a/xCAT-UI/xcat/plugins/webportal.pm
+++ b/xCAT-UI/xcat/plugins/webportal.pm
@@ -38,7 +38,8 @@ sub process_request {
'provzlinux' => \&provzlinux,
'clonezlinux' => \&clonezlinux,
'genhostip' => \&genhostip,
- 'getmaxvm' => \&getmaxvm
+ 'getmaxvm' => \&getmaxvm,
+ 'getuserprivilege' => \&getuserprivilege
);
# Check if the request is authorized
@@ -769,4 +770,39 @@ sub getmaxvm {
$callback->( { data => "Max allowed: $max" } );
}
+
+sub getuserprivilege {
+ # Get the user privilege
+ my ( $request, $callback, $sub_req ) = @_;
+ my $user = $request->{arg}->[1];
+ if (!$user) {
+ $callback->( { data => "(Error) No user name is specified" } );
+ return;
+ }
+
+ my @args;
+ my $privilege = "user";
+
+ # Look in 'policy' table
+ my $tab = xCAT::Table->new( 'policy', -create => 1, -autocommit => 0 );
+ my @results = $tab->getAllAttribsWhere( "name='" . $user . "'", 'comments' );
+ foreach (@results) {
+ if ( $_->{'comments'} ) {
+ @args = split( ';', $_->{'comments'} );
+
+ # Extract user privilege
+ foreach (@args) {
+ if ($_ =~ m/privilege:/i) {
+ $_ =~ s/privilege://g;
+ $privilege = $_;
+ $privilege =~ s/\s*$//; # Trim right
+ $privilege =~ s/^\s*//; # Trim left
+ last;
+ }
+ }
+ }
+ }
+
+ $callback->( { data => "Privilege: $privilege" } );
+}
1;
\ No newline at end of file