From e469f6b91f266a0f5a0fd90dcc5b0802f09bcbc3 Mon Sep 17 00:00:00 2001
From: phamt
Date: Fri, 16 Sep 2011 21:35:54 +0000
Subject: [PATCH] Check in self-service portal code. This is currently set for
System z, more work needs to be done to customize it for other platforms.
git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@10543 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
---
xCAT-UI/css/service.css | 365 +++++
xCAT-UI/css/style.css | 41 +-
xCAT-UI/js/custom/hmc.js | 4 +-
xCAT-UI/js/service/service.js | 2350 +++++++++++++++++++++++++++++++++
xCAT-UI/js/service/utils.js | 321 +++++
xCAT-UI/js/srv_xcatauth.js | 90 ++
xCAT-UI/lib/srv_cmd.php | 192 +++
xCAT-UI/lib/srv_functions.php | 324 +++++
xCAT-UI/lib/srv_log.php | 39 +
xCAT-UI/lib/srv_logout.php | 10 +
xCAT-UI/lib/ui.php | 8 +-
xCAT-UI/service.php | 87 ++
12 files changed, 3808 insertions(+), 23 deletions(-)
create mode 100644 xCAT-UI/css/service.css
create mode 100644 xCAT-UI/js/service/service.js
create mode 100644 xCAT-UI/js/service/utils.js
create mode 100644 xCAT-UI/js/srv_xcatauth.js
create mode 100644 xCAT-UI/lib/srv_cmd.php
create mode 100644 xCAT-UI/lib/srv_functions.php
create mode 100644 xCAT-UI/lib/srv_log.php
create mode 100644 xCAT-UI/lib/srv_logout.php
create mode 100644 xCAT-UI/service.php
diff --git a/xCAT-UI/css/service.css b/xCAT-UI/css/service.css
new file mode 100644
index 000000000..721460bf7
--- /dev/null
+++ b/xCAT-UI/css/service.css
@@ -0,0 +1,365 @@
+/*--- Dialogs ---*/
+.ui-dialog input {
+ border: solid 1px;
+ font: 12px verdana, arial, helvetica, sans-serif;
+}
+
+.ui-dialog label,.ui-dialog input,.ui-dialog p,.ui-dialog button,.ui-dialog td {
+ font: 12px verdana, arial, helvetica, sans-serif;
+}
+
+.ui-widget {
+ font: 12px verdana, arial, helvetica, sans-serif;
+}
+
+/*--- Tooltip ---*/
+.tooltip {
+ background-color: #000;
+ border: 1px solid #fff;
+ padding: 10px 15px;
+ display: none;
+ color: #fff;
+ text-align: left;
+ max-width: 300px;
+ font-size: 10px;
+ /* Outline radius for firefox only */
+ -moz-box-shadow: 0 0 10px #000;
+ -webkit-box-shadow: 0 0 10px #000;
+}
+
+.tooltip h3 {
+ margin: 0px;
+}
+
+/*--- Login dialog ---*/
+#logdialog {
+ font: 12px verdana, arial, helvetica, sans-serif;
+ width: 600px;
+}
+
+#logdialog table {
+ border: solid 0px;
+}
+
+#logdialog td {
+ width: 100px;
+ height: 35px;
+ color: #0078AE;
+ font-weight: bold;
+ border: solid 0px;
+}
+
+#logdialog input {
+ width: 210px;
+ border: solid 1px #0078AE;
+ font-size: 12px;
+ padding-bottom: 5px;
+}
+
+#logdialog p {
+ font-size: 18px;
+}
+
+#logdialog button {
+ font-weight: bold;
+ width: 90px;
+ float: right;
+}
+
+#loginput {
+ background-color: #f5f5f5;
+ height: 300px;
+}
+
+#loginfo {
+ margin: 5px 0px;
+ text-align: right;
+ color: #f5f5f5;
+ font-weight:bold;
+}
+
+/*--- Header ---*/
+#header {
+ height: 40px;
+ width: 1000px;
+ margin: 0px auto;
+ -moz-border-radius: .3em;
+ -webkit-border-radius: .3em;
+ border-radius: .3em;
+}
+
+/* User name and log out */
+#header div {
+ float: right;
+}
+
+#header div span {
+ color: #424242;
+ padding: 2px 15px 0px 2px; /* Top right left bottom*/
+ text-align: right;
+ text-decoration: none;
+ display: block;
+}
+
+#header div a {
+ padding: 3px 15px 0px 3px; /* Top right left bottom*/
+ text-align: right;
+ color: blue;
+ font-weight: normal;
+ text-decoration: none;
+ display: block;
+ cursor: pointer;
+}
+
+#header div a:hover {
+ color: red;
+}
+
+#layoutselector {
+ padding: 2px 10px 0px 2px; /* Top right left bottom*/
+ text-align: right;
+ color: #FFC125;
+ text-decoration: none;
+ display: block;
+}
+
+/*--- Body and content ---*/
+body {
+ background-color: #1C1C1C;
+ font: 12px verdana, arial, helvetica, sans-serif;
+}
+
+.content {
+ -moz-border-radius: .3em;
+ -webkit-border-radius: .3em;
+ border-radius: .3em;
+ width: 1000px;
+ min-height: 600px;
+ margin: 10px auto;
+ background-color: white;
+ overflow: auto;
+}
+
+#content ul.ui-widget-header {
+ border-color: #4297D7 #4297D7 #7BB642;
+ border-width: 1px 1px 4px;
+}
+
+.ui-state-highlight {
+ vertical-align: top;
+ word-wrap: break-word;
+}
+
+/*--- jQuery tabs ---*/
+.tab {
+ font: 12px verdana, arial, helvetica, sans-serif;
+ border-style: none;
+ overflow: visible;
+}
+
+.ui-icon-close {
+ float: left;
+ margin: 0.4em 0.2em 0 0;
+ cursor: pointer;
+}
+
+/*--- Inventory and user entry ---*/
+table {
+ border-width: 1px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-collapse: collapse;
+}
+
+/*--- jQuery datatable ---*/
+.dataTables_wrapper {
+ overflow: auto;
+ width: auto;
+ margin: 10px auto;
+}
+
+/*** Show X entries ***/
+.dataTables_length {
+ width: 40%;
+ float: left;
+ padding: 10px 20px;
+ text-align: left;
+}
+
+/*** Search ***/
+.dataTables_filter {
+ width: 40%;
+ margin: 10px 0px;
+ display: block;
+ float: right;
+ text-align: right;
+}
+
+.tab input,select {
+ font: 12px verdana, arial, helvetica, sans-serif;
+ border: solid 1px;
+ padding: 4px;
+}
+
+.sorting,.sorting_asc,.sorting_desc {
+ background: none;
+}
+
+/*** Showing X to X of X entries ***/
+.dataTables_info {
+ padding: 10px 20px;
+ width: 40%;
+ float: left;
+}
+
+/*** < > buttons ***/
+.paginate_disabled_previous,.paginate_enabled_previous,.paginate_disabled_next,.paginate_enabled_next
+ {
+ height: 19px;
+ width: 19px;
+ margin-left: 2px;
+ float: left;
+}
+
+/*** Table ***/
+.datatable {
+ width: 100%;
+ border-width: 1px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-collapse: collapse;
+ display: inline-table;
+}
+
+/*** Row color (odd) ***/
+.datatable tr.odd {
+ background-color: white;
+}
+
+.datatable tr.odd td.sorting_1 {
+ background-color: white;
+}
+
+/*** Row color (even) ***/
+.datatable tr.even {
+ background-color: white;
+}
+
+.datatable tr.even td.sorting_1 {
+ background-color: white;
+}
+
+.datatable a {
+ text-decoration: none;
+ color: blue;
+ cursor: pointer;
+}
+
+.datatable a:hover {
+ color: red;
+}
+
+/*--- Superfish menu ---*/
+.sf-menu {
+ background : none repeat scroll 0 0 #2191C0;
+ border :1px solid #f5f5f5;
+ border-radius: 0.3em 0.3em 0.3em 0.3em;
+}
+
+.sf-menu a {
+ color: white;
+ padding: 10px 25px;
+ font-weight: bold;
+}
+
+.sf-sub-indicator{
+ right:0;
+}
+
+.sf-shadow ul {
+ padding: 0px;
+}
+
+.sf-menu li:hover, .sf-menu li.sfHover {
+ background: #79C9EC;
+}
+
+/*--- Generic tags ---*/
+p {
+ word-wrap: break-word;
+}
+
+a {
+ cursor: pointer;
+ color: blue;
+}
+
+th {
+ font: bold 12px verdana, arial, helvetica, sans-serif;
+ border-width: 1px;
+ padding: 8px 0px;
+ min-width: 50px;
+ border-style: solid;
+ vertical-align: middle;
+ text-align: center;
+}
+
+td {
+ font: 12px verdana, arial, helvetica, sans-serif;
+ color: #424242;
+ padding: 8px 0px;
+ border-width: 1px;
+ border-style: solid;
+ vertical-align: middle;
+ text-align: center;
+}
+
+fieldset {
+ margin-bottom: 5px;
+ border-width: 1px 0 0 0;
+ border-style: solid none none none;
+}
+
+label {
+ color: #424242;
+ display: inline-block;
+ line-height: 1.5;
+ vertical-align: top;
+ width: 140px;
+}
+
+legend {
+ font: 12px verdana, arial, helvetica, sans-serif;
+ color: #424242;
+ font-weight: bold;
+ padding: 10px 15px;
+}
+
+ol {
+ margin: 0;
+ padding: 0;
+}
+
+li {
+ list-style: none;
+ padding: 5px 5px 5px 20px;
+ margin: 0;
+}
+
+input,textarea,select {
+ font: 12px verdana, arial, helvetica, sans-serif;
+ border: solid 1px;
+ padding: 5px;
+ display: inline-table;
+}
+
+table a {
+ font: 12px verdana, arial, helvetica, sans-serif;
+ text-decoration: none;
+ color: blue;
+ cursor: pointer;
+}
+
+table a:hover {
+ color: red;
+}
\ No newline at end of file
diff --git a/xCAT-UI/css/style.css b/xCAT-UI/css/style.css
index 95552110f..611ebb816 100644
--- a/xCAT-UI/css/style.css
+++ b/xCAT-UI/css/style.css
@@ -31,43 +31,50 @@
margin: 0px;
}
-/*--------------- login dialog ---------*/
+/*--- Login dialog ---*/
#logdialog {
+ font: 12px verdana, arial, helvetica, sans-serif;
width: 600px;
}
-#logdialog td{
- width: 110px;
- height: 30px;
+#logdialog table {
+ border: solid 0px;
+ margin: 0px auto;
+}
+
+#logdialog td {
+ width: 100px;
+ height: 35px;
color: #0078AE;
- font-size: 14px;
font-weight: bold;
- border-width: 0px;
+ border: solid 0px;
}
-#logdialog input{
- width: 219px;
+#logdialog input {
+ width: 210px;
border: solid 1px #0078AE;
- font-size: 14px;
+ font-size: 12px;
+ padding-bottom: 5px;
}
-#logdialog p{
-
+#logdialog p {
font-size: 18px;
}
-#logdialog button{
+#logdialog button {
font-weight: bold;
width: 90px;
+ float: right;
}
#loginput {
background-color: #f5f5f5;
- height: 260px;
+ height: 280px;
}
-#loginfo{
- text-align:right;
+#loginfo {
+ margin: 5px 0px;
+ text-align: right;
color: #f5f5f5;
font-weight:bold;
}
@@ -77,7 +84,7 @@
height: 39px;
width: 1000px;
margin: 0px auto;
- background: url(../images/header-gloss-wave.png) 50% 50% repeat-x;
+ background: url(../images/jquery/default/ui-bg_highlight-soft_75_2191c0_1x100.png) 50% 50% repeat-x;
-moz-border-radius: .5em;
-webkit-border-radius: .5em;
border-radius: .5em;
@@ -149,7 +156,7 @@
/*--------------- Body and content ---------------*/
body {
- background-color: #1C1C1C;
+ background: #1C1C1C;
font: 12px verdana, arial, helvetica, sans-serif;
}
diff --git a/xCAT-UI/js/custom/hmc.js b/xCAT-UI/js/custom/hmc.js
index ad5afbd3c..c96aefc95 100644
--- a/xCAT-UI/js/custom/hmc.js
+++ b/xCAT-UI/js/custom/hmc.js
@@ -122,7 +122,7 @@ hmcPlugin.prototype.loadProvisionPage = function(tabId) {
var provForm = $('
');
// Create info bar
- var infoBar = createInfoBar('Provision a node on system P server.');
+ var infoBar = createInfoBar('Provision a node on System p.');
provForm.append(infoBar);
// Append to provision tab
@@ -369,7 +369,7 @@ function addHmcNode(){
}
/**
- * Add system p node, contains frame, cec, lpar
+ * Add System p node, contains frame, cec, lpar
*
* @return Nothing
*/
diff --git a/xCAT-UI/js/service/service.js b/xCAT-UI/js/service/service.js
new file mode 100644
index 000000000..8faffbe40
--- /dev/null
+++ b/xCAT-UI/js/service/service.js
@@ -0,0 +1,2350 @@
+/**
+ * Global variables
+ */
+var serviceTabs;
+var nodeName;
+var nodePath;
+var nodeStatus;
+var gangliaTimer;
+
+/**
+ * Initialize service page
+ */
+function initServicePage() {
+ // Reuqired JQuery plugins
+ includeJs("js/jquery/jquery.dataTables.min.js");
+ includeJs("js/jquery/jquery.cookie.min.js");
+ includeJs("js/jquery/tooltip.min.js");
+ includeJs("js/jquery/superfish.min.js");
+ includeJs("js/jquery/jquery.jqplot.min.js");
+ includeJs("js/jquery/jqplot.dateAxisRenderer.min.js");
+
+ // Show service page
+ $("#content").children().remove();
+ includeJs("js/service/service.js");
+ includeJs("js/service/utils.js");
+ loadServicePage();
+}
+
+/**
+ * Load service page
+ */
+function loadServicePage() {
+ // If the page is loaded
+ if ($('#content').children().length) {
+ // Do not load again
+ return;
+ }
+
+ // Create manage and provision tabs
+ serviceTabs = new Tab();
+ serviceTabs.init();
+ $('#content').append(serviceTabs.object());
+
+ var manageTabId = 'manageTab';
+ serviceTabs.add(manageTabId, 'Manage', '', false);
+ loadManagePage(manageTabId);
+
+ var provTabId = 'provisionTab';
+ serviceTabs.add(provTabId, 'Provision', '', false);
+ loadzProvisionPage(provTabId);
+
+ serviceTabs.select(manageTabId);
+
+ // Get zVM host names
+ if (!$.cookie('srv_zvm')){
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'lszvm',
+ msg : ''
+ },
+
+ success : function(data) {
+ setzVMCookies(data);
+ loadzVMs();
+ }
+ });
+ } else {
+ loadzVMs();
+ }
+
+ // Get OS image names
+ if (!$.cookie('srv_imagenames')){
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'osimage',
+ msg : ''
+ },
+
+ success : function(data) {
+ setOSImageCookies(data);
+ loadOSImages();
+ }
+ });
+ } else {
+ loadOSImages();
+ }
+
+ // Get contents of hosts table
+ if (!$.cookie('srv_groups')) {
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'hosts',
+ msg : ''
+ },
+
+ success : function(data) {
+ setGroupCookies(data);
+ loadGroups();
+ }
+ });
+ } else {
+ loadGroups();
+ }
+
+ // Get nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ setUserNodes(data);
+ getUserNodesDef();
+ getNodesCurrentLoad();
+ }
+ });
+
+
+}
+
+/**
+ * Load manage page
+ *
+ * @param tabId
+ * Tab ID where page will reside
+ * @return Nothing
+ */
+function loadManagePage(tabId) {
+ // Create manage form
+ var loader = createLoader('');
+ var manageForm = $('
').append(loader);
+
+ // Append to manage tab
+ $('#' + tabId).append(manageForm);
+}
+
+/**
+ * Get the user nodes definitions
+ */
+function getUserNodesDef() {
+ var userName = $.cookie('srv_usrname');
+ var userNodes = $.cookie(userName + '_usrnodes');
+ if (userNodes) {
+ // Get nodes definitions
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'lsdef',
+ tgt : '',
+ args : userNodes,
+ msg : ''
+ },
+
+ success : loadNodesTable
+ });
+ } else {
+ prompt('Warning', $('Your session has expired! Please log out and back in.
'));
+ }
+}
+
+/**
+ * Load user nodes definitions into a table
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function loadNodesTable(data) {
+ // Clear the tab before inserting the table
+ $('#manageTab').children().remove();
+
+ // Nodes datatable ID
+ var nodesDTId = 'userNodesDT';
+
+ // Hash of node attributes
+ var attrs = new Object();
+ // Node attributes
+ var headers = new Object();
+ var node, args;
+ // Create hash of node attributes
+ for (var i in data.rsp) {
+ // Get node name
+ if (data.rsp[i].indexOf('Object name:') > -1) {
+ var temp = data.rsp[i].split(': ');
+ node = jQuery.trim(temp[1]);
+
+ // Create a hash for the node attributes
+ attrs[node] = new Object();
+ i++;
+ }
+
+ // Get key and value
+ args = data.rsp[i].split('=', 2);
+ var key = jQuery.trim(args[0]);
+ var val = jQuery.trim(data.rsp[i].substring(data.rsp[i].indexOf('=') + 1, data.rsp[i].length));
+
+ // Create a hash table
+ attrs[node][key] = val;
+ headers[key] = 1;
+ }
+
+ // Sort headers
+ var sorted = new Array();
+ var attrs2hide = new Array('status', 'statustime', 'appstatus', 'appstatustime', 'usercomment');
+ var attrs2show = new Array('arch', 'groups', 'hcp', 'hostnames', 'ip', 'os', 'userid');
+ for (var key in headers) {
+ // Show node attributes
+ if (jQuery.inArray(key, attrs2show) > -1) {
+ sorted.push(key);
+ }
+ }
+ sorted.sort();
+
+ // Add column for check box, node, ping, power, monitor, and comments
+ sorted.unshift(' ',
+ 'node',
+ 'status ',
+ 'power ',
+ 'monitor ',
+ 'comments');
+
+ // Create a datatable
+ var nodesDT = new DataTable(nodesDTId);
+ nodesDT.init(sorted);
+
+ // Go through each node
+ for (var node in attrs) {
+ // Create a row
+ var row = new Array();
+
+ // Create a check box, node link, and get node status
+ var checkBx = $(' ');
+ var nodeLink = $('' + node + ' ').bind('click', loadNode);
+
+ // If there is no status attribute for the node, do not try to access hash table
+ // Else the code will break
+ var status = '';
+ if (attrs[node]['status']) {
+ status = attrs[node]['status'].replace('sshd', 'ping');
+ }
+
+ // Push in checkbox, node, status, monitor, and power
+ row.push(checkBx, nodeLink, status, '', '');
+
+ // If the node attributes are known (i.e the group is known)
+ if (attrs[node]['groups']) {
+ // Put in comments
+ var comments = attrs[node]['usercomment'];
+ // If no comments exists, show 'No comments' and set icon image source
+ var iconSrc;
+ if (!comments) {
+ comments = 'No comments';
+ iconSrc = 'images/nodes/ui-icon-no-comment.png';
+ } else {
+ iconSrc = 'images/nodes/ui-icon-comment.png';
+ }
+
+ // Create comments icon
+ var tipID = node + 'Tip';
+ var icon = $(' ').css({
+ 'width': '18px',
+ 'height': '18px'
+ });
+
+ // Create tooltip
+ var tip = createCommentsToolTip(comments);
+ var col = $(' ').append(icon);
+ col.append(tip);
+ row.push(col);
+
+ // Generate tooltips
+ icon.tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.8,
+ relative: true,
+ delay: 500
+ });
+ } else {
+ // Do not put in comments if attributes are not known
+ row.push('');
+ }
+
+ // Go through each header
+ for (var i = 6; i < sorted.length; i++) {
+ // Add the node attributes to the row
+ var key = sorted[i];
+
+ // Do not put comments and status in twice
+ if (key != 'usercomment' && key != 'status' && key.indexOf('statustime') < 0) {
+ var val = attrs[node][key];
+ if (val) {
+ row.push($('' + val + ' '));
+ } else {
+ row.push('');
+ }
+ }
+ }
+
+ // Add the row to the table
+ nodesDT.add(row);
+ }
+
+ // Create info bar
+ var infoBar = createInfoBar('Manage and monitor your Linux virtual machines on System z.');
+ $('#manageTab').append(infoBar);
+
+ // Insert action bar and nodes datatable
+ $('#manageTab').append(nodesDT.object());
+
+ // Turn table into a datatable
+ $('#' + nodesDTId).dataTable({
+ 'iDisplayLength': 50,
+ 'bLengthChange': false,
+ "sScrollX": "100%",
+ "sScrollXInner": "110%"
+ });
+
+ // Set datatable header class to add color
+ $('.datatable thead').attr('class', 'ui-widget-header');
+
+ // Do not sort ping, power, and comment column
+ var cols = $('#' + nodesDTId + ' thead tr th').click(function() {
+ getNodeAttrs(group);
+ });
+ var checkboxCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)');
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ var monitorCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ var commentCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)');
+ checkboxCol.unbind('click');
+ pingCol.unbind('click');
+ powerCol.unbind('click');
+ monitorCol.unbind('click');
+ commentCol.unbind('click');
+
+ // Refresh the node ping, power, and monitor status on-click
+ var nodes = getNodesShown(nodesDTId);
+ pingCol.find('span a').click(function() {
+ refreshNodeStatus(nodes);
+ });
+ powerCol.find('span a').click(function() {
+ refreshPowerStatus(nodes);
+ });
+ monitorCol.find('span a').click(function() {
+ refreshGangliaStatus(nodes);
+ });
+
+ // Create actions menu
+ // Power on
+ var powerOnLnk = $('Power on ');
+ powerOnLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'on');
+ }
+ });
+
+ // Power off
+ var powerOffLnk = $('Power off ');
+ powerOffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ powerNode(tgtNodes, 'off');
+ }
+ });
+
+ // Turn monitoring on
+ var monitorOnLnk = $('Monitor on ');
+ monitorOnLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ monitorNode(tgtNodes, 'on');
+ }
+ });
+
+ // Turn monitoring off
+ var monitorOffLnk = $('Monitor off ');
+ monitorOffLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ monitorNode(tgtNodes, 'off');
+ }
+ });
+
+ // Delete
+ var deleteLnk = $('Delete ');
+ deleteLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ deleteNode(tgtNodes);
+ }
+ });
+
+ // Unlock
+ var unlockLnk = $('Unlock ');
+ unlockLnk.click(function() {
+ var tgtNodes = getNodesChecked(nodesDTId);
+ if (tgtNodes) {
+ unlockNode(tgtNodes);
+ }
+ });
+
+ // Prepend menu to datatable
+ var actionsLnk = 'Actions ';
+ var actionMenu = createMenu([deleteLnk, powerOnLnk, powerOffLnk, monitorOnLnk, monitorOffLnk, unlockLnk]);
+ var menu = createMenu([[actionsLnk, actionMenu]]);
+ menu.superfish();
+ $('#' + nodesDTId + '_filter').css('display', 'inline-block');
+ $('#' + nodesDTId + '_wrapper').prepend(menu);
+
+ $('.sf-menu li:hover, .sf-menu li.sfHover').attr('class', 'ui-widget-header');
+
+ // Get power and monitor status
+ var nodes = getNodesShown(nodesDTId);
+ refreshPowerStatus(nodes);
+ refreshGangliaStatus(nodes);
+}
+
+/**
+ * Refresh ping status for each node
+ *
+ * @param nodes
+ * Nodes to get ping status
+ * @return Nothing
+ */
+function refreshNodeStatus(nodes) {
+ // Show ping loader
+ var nodesDTId = 'userNodesDT';
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ pingCol.find('img').show();
+
+ // Get the node ping status
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'nodestat',
+ tgt : nodes,
+ args : '-u',
+ msg : ''
+ },
+
+ success : loadNodePing
+ });
+}
+
+/**
+ * Load node ping status for each node
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+function loadNodePing(data) {
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var rsp = data.rsp;
+ var args, rowPos, node, status;
+
+ // Get all nodes within datatable
+ for (var i in rsp) {
+ args = rsp[i].split(':');
+
+ // args[0] = node and args[1] = status
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]).replace('sshd', 'ping');
+
+ // Get row containing node
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // Update ping status column
+ datatable.fnUpdate(status, rowPos, 2, false);
+ }
+
+ // Hide status loader
+ var pingCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)');
+ pingCol.find('img').hide();
+ datatable.fnDraw();
+}
+
+/**
+ * Refresh power status for each node
+ *
+ * @param nodes
+ * Nodes to get power status
+ * @return Nothing
+ */
+function refreshPowerStatus(nodes) {
+ // Show power loader
+ var nodesDTId = 'userNodesDT';
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').show();
+
+ // Get power status
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : nodes,
+ args : 'stat',
+ msg : ''
+ },
+
+ success : loadPowerStatus
+ });
+}
+
+/**
+ * Load power status for each node
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+function loadPowerStatus(data) {
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var power = data.rsp;
+ var rowPos, node, status, args;
+
+ for (var i in power) {
+ // power[0] = nodeName and power[1] = state
+ args = power[i].split(':');
+ node = jQuery.trim(args[0]);
+ status = jQuery.trim(args[1]);
+
+ // Get the row containing the node
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // Update the power status column
+ datatable.fnUpdate(status, rowPos, 3, false);
+ }
+
+ // Hide power loader
+ var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)');
+ powerCol.find('img').hide();
+ datatable.fnDraw();
+}
+
+/**
+ * Refresh the status of Ganglia for each node
+ *
+ * @param nodes
+ * Nodes to get Ganglia status
+ * @return Nothing
+ */
+function refreshGangliaStatus(nodes) {
+ // Show ganglia loader
+ var nodesDTId = 'userNodesDT';
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').show();
+
+ // Get the status of Ganglia
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastatus;' + nodes,
+ msg : ''
+ },
+
+ success : loadGangliaStatus
+ });
+}
+
+/**
+ * Load the status of Ganglia for a given group
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+function loadGangliaStatus(data) {
+ // Get datatable
+ var nodesDTId = 'userNodesDT';
+ var datatable = $('#' + nodesDTId).dataTable();
+ var ganglia = data.rsp;
+ var rowNum, node, status;
+
+ for ( var i in ganglia) {
+ // ganglia[0] = nodeName and ganglia[1] = state
+ node = jQuery.trim(ganglia[i][0]);
+ status = jQuery.trim(ganglia[i][1]);
+
+ // Get the row containing the node
+ rowNum = findRow(node, '#' + nodesDTId, 1);
+
+ // Update the power status column
+ datatable.fnUpdate(status, rowNum, 4);
+ }
+
+ // Hide Ganglia loader
+ var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)');
+ gangliaCol.find('img').hide();
+ datatable.fnDraw();
+}
+
+/**
+ * Load inventory for given node
+ *
+ * @param e
+ * Windows event
+ * @return Nothing
+ */
+function loadNode(e) {
+ if (!e) {
+ e = window.event;
+ }
+
+ // Get node that was clicked
+ var node = (e.target) ? e.target.id : e.srcElement.id;
+
+ // Create a new tab to show inventory
+ var tabId = node + '_inventory';
+
+ if(!$('#' + tabId).length) {
+ // Add new tab, only if one does not exist
+ var loader = createLoader(node + 'Loader');
+ loader = $(' ').append(loader);
+ serviceTabs.add(tabId, node, loader, true);
+
+ // Get node inventory
+ var msg = 'out=' + tabId + ',node=' + node;
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rinv',
+ tgt : node,
+ args : 'all',
+ msg : msg
+ },
+
+ success : showInventory
+ });
+ }
+
+ // Select new tab
+ serviceTabs.select(tabId);
+}
+
+/**
+ * Show node inventory
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function showInventory(data) {
+ var args = data.msg.split(',');
+
+ // Get tab ID
+ var tabId = args[0].replace('out=', '');
+ // Get node
+ var node = args[1].replace('node=', '');
+ // Get node inventory
+ var inv = data.rsp[0].split(node + ':');
+
+ // Remove loader
+ $('#' + tabId).find('img').remove();
+
+ // Create array of property keys
+ var keys = new Array('userId', 'host', 'os', 'arch', 'hcp', 'priv', 'memory', 'proc', 'disk', 'nic');
+
+ // Create hash table for property names
+ var attrNames = new Object();
+ attrNames['userId'] = 'z/VM UserID:';
+ attrNames['host'] = 'z/VM Host:';
+ attrNames['os'] = 'Operating System:';
+ attrNames['arch'] = 'Architecture:';
+ attrNames['hcp'] = 'HCP:';
+ attrNames['priv'] = 'Privileges:';
+ attrNames['memory'] = 'Total Memory:';
+ attrNames['proc'] = 'Processors:';
+ attrNames['disk'] = 'Disks:';
+ attrNames['nic'] = 'NICs:';
+
+ // Create hash table for node attributes
+ var attrs = getAttrs(keys, attrNames, inv);
+
+ // Create division to hold inventory
+ var invDivId = node + 'Inventory';
+ var invDiv = $('
');
+
+ var infoBar = createInfoBar('Below is the inventory for the virtual machine you selected.');
+ invDiv.append(infoBar);
+
+ /**
+ * General info section
+ */
+ var fieldSet = $(' ');
+ var legend = $('General ');
+ fieldSet.append(legend);
+ var oList = $(' ');
+ var item, label, args;
+
+ // Loop through each property
+ for ( var k = 0; k < 5; k++) {
+ // Create a list item for each property
+ item = $(' ');
+
+ // Create a label - Property name
+ label = $('' + attrNames[keys[k]] + ' ');
+ item.append(label);
+
+ for ( var l = 0; l < attrs[keys[k]].length; l++) {
+ // Create a input - Property value(s)
+ // Handle each property uniquely
+ item.append(attrs[keys[k]][l]);
+ }
+
+ oList.append(item);
+ }
+ // Append to inventory form
+ fieldSet.append(oList);
+ invDiv.append(fieldSet);
+
+ /**
+ * Monitoring section
+ */
+ fieldSet = $(' ');
+ legend = $('Monitoring ');
+ fieldSet.append(legend);
+ getMonitorMetrics(node);
+
+ // Append to inventory form
+ invDiv.append(fieldSet);
+
+ /**
+ * Hardware info section
+ */
+ var hwList, hwItem;
+ fieldSet = $(' ');
+ legend = $('Hardware');
+ fieldSet.append(legend);
+ oList = $(' ');
+
+ // Loop through each property
+ var label;
+ for (k = 5; k < keys.length; k++) {
+ // Create a list item
+ item = $(' ');
+
+ // Create a list to hold the property value(s)
+ hwList = $('');
+ hwItem = $(' ');
+
+ /**
+ * Privilege section
+ */
+ if (keys[k] == 'priv') {
+ // Create a label - Property name
+ label = $('' + attrNames[keys[k]].replace(':', '') + ' ');
+ item.append(label);
+
+ // Loop through each line
+ for (l = 0; l < attrs[keys[k]].length; l++) {
+ // Create a new list item for each line
+ hwItem = $(' ');
+
+ // Determine privilege
+ args = attrs[keys[k]][l].split(' ');
+ if (args[0] == 'Directory:') {
+ label = $('' + args[0] + ' ');
+ hwItem.append(label);
+ hwItem.append(args[1]);
+ } else if (args[0] == 'Currently:') {
+ label = $('' + args[0] + ' ');
+ hwItem.append(label);
+ hwItem.append(args[1]);
+ }
+
+ hwList.append(hwItem);
+ }
+
+ item.append(hwList);
+ }
+
+ /**
+ * Memory section
+ */
+ else if (keys[k] == 'memory') {
+ // Create a label - Property name
+ label = $('' + attrNames[keys[k]].replace(':', '') + ' ');
+ item.append(label);
+
+ // Loop through each value line
+ for (l = 0; l < attrs[keys[k]].length; l++) {
+ // Create a new list item for each line
+ hwItem = $(' ');
+ hwItem.append(attrs[keys[k]][l]);
+ hwList.append(hwItem);
+ }
+
+ item.append(hwList);
+ }
+
+ /**
+ * Processor section
+ */
+ else if (keys[k] == 'proc') {
+ // Create a label - Property name
+ label = $('' + attrNames[keys[k]].replace(':', '') + ' ');
+ item.append(label);
+
+ // Create a table to hold processor data
+ var procTable = $('');
+ var procBody = $(' ');
+
+ // Table columns - Type, Address, ID, Base, Dedicated, and Affinity
+ var procTabRow = $('');
+ procTable.append(procTabRow);
+ var procType, procAddr, procId, procAff;
+
+ // Loop through each processor
+ var n, temp;
+ for (l = 0; l < attrs[keys[k]].length; l++) {
+ if (attrs[keys[k]][l]) {
+ args = attrs[keys[k]][l].split(' ');
+
+ // Get processor type, address, ID, and affinity
+ n = 3;
+ temp = args[args.length - n];
+ while (!jQuery.trim(temp)) {
+ n = n + 1;
+ temp = args[args.length - n];
+ }
+ procType = $('' + temp + ' ');
+ procAddr = $('' + args[1] + ' ');
+ procId = $('' + args[5] + ' ');
+ procAff = $('' + args[args.length - 1] + ' ');
+
+ // Base processor
+ if (args[6] == '(BASE)') {
+ baseProc = $('' + true + ' ');
+ } else {
+ baseProc = $('' + false + ' ');
+ }
+
+ // Dedicated processor
+ if (args[args.length - 3] == 'DEDICATED') {
+ dedicatedProc = $('' + true + ' ');
+ } else {
+ dedicatedProc = $('' + false + ' ');
+ }
+
+ // Create a new row for each processor
+ procTabRow = $(' ');
+ procTabRow.append(procType);
+ procTabRow.append(procAddr);
+ procTabRow.append(procId);
+ procTabRow.append(baseProc);
+ procTabRow.append(dedicatedProc);
+ procTabRow.append(procAff);
+ procBody.append(procTabRow);
+ }
+ }
+
+ procTable.append(procBody);
+ item.append(procTable);
+ }
+
+ /**
+ * Disk section
+ */
+ else if (keys[k] == 'disk') {
+ // Create a label - Property name
+ label = $('' + attrNames[keys[k]].replace(':', '') + ' ');
+ item.append(label);
+
+ // Create a table to hold disk (DASD) data
+ var dasdTable = $('');
+ var dasdBody = $(' ');
+
+ // Table columns - Virtual Device, Type, VolID, Type of Access, and Size
+ var dasdTabRow = $('');
+ dasdTable.append(dasdTabRow);
+ var dasdVDev, dasdType, dasdVolId, dasdAccess, dasdSize;
+
+ // Loop through each DASD
+ for (l = 0; l < attrs[keys[k]].length; l++) {
+ if (attrs[keys[k]][l]) {
+ args = attrs[keys[k]][l].split(' ');
+
+ // Get DASD virtual device, type, volume ID, access, and size
+ dasdVDev = $('' + args[1] + ' ');
+ dasdType = $('' + args[2] + ' ');
+ dasdVolId = $('' + args[3] + ' ');
+ dasdAccess = $('' + args[4] + ' ');
+ dasdSize = $('' + args[args.length - 9] + ' ' + args[args.length - 8] + ' ');
+
+ // Create a new row for each DASD
+ dasdTabRow = $(' ');
+ dasdTabRow.append(dasdVDev);
+ dasdTabRow.append(dasdType);
+ dasdTabRow.append(dasdVolId);
+ dasdTabRow.append(dasdAccess);
+ dasdTabRow.append(dasdSize);
+ dasdBody.append(dasdTabRow);
+ }
+ }
+
+ dasdTable.append(dasdBody);
+ item.append(dasdTable);
+ }
+
+ /**
+ * NIC section
+ */
+ else if (keys[k] == 'nic') {
+ // Create a label - Property name
+ label = $('' + attrNames[keys[k]].replace(':', '') + ' ');
+ item.append(label);
+
+ // Create a table to hold NIC data
+ var nicTable = $('');
+ var nicBody = $(' ');
+
+ // Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name
+ var nicTabRow = $('');
+ nicTable.append(nicTabRow);
+ var nicVDev, nicType, nicPortName, nicNumOfDevs, nicLanName;
+
+ // Loop through each NIC (Data contained in 2 lines)
+ for (l = 0; l < attrs[keys[k]].length; l = l + 2) {
+ if (attrs[keys[k]][l]) {
+ args = attrs[keys[k]][l].split(' ');
+
+ // Get NIC virtual device, type, port name, and number of devices
+ nicVDev = $('' + args[1] + ' ');
+ nicType = $('' + args[3] + ' ');
+ nicPortName = $('' + args[10] + ' ');
+ nicNumOfDevs = $('' + args[args.length - 1] + ' ');
+
+ args = attrs[keys[k]][l + 1].split(' ');
+ nicLanName = $('' + args[args.length - 2] + ' ' + args[args.length - 1] + ' ');
+
+ // Create a new row for each DASD
+ nicTabRow = $(' ');
+ nicTabRow.append(nicVDev);
+ nicTabRow.append(nicType);
+ nicTabRow.append(nicPortName);
+ nicTabRow.append(nicNumOfDevs);
+ nicTabRow.append(nicLanName);
+
+ nicBody.append(nicTabRow);
+ }
+ }
+
+ nicTable.append(nicBody);
+ item.append(nicTable);
+ }
+
+ oList.append(item);
+ }
+
+ // Append inventory to division
+ fieldSet.append(oList);
+ invDiv.append(fieldSet);
+ invDiv.find('th').css({
+ 'padding': '5px 10px',
+ 'font-weight': 'bold'
+ });
+
+ // Append to tab
+ $('#' + tabId).append(invDiv);
+}
+
+/**
+ * Load provision page (z)
+ *
+ * @param tabId
+ * Tab ID where page will reside
+ * @return Nothing
+ */
+function loadzProvisionPage(tabId) {
+ // Create provision form
+ var provForm = $('
');
+
+ // Create info bar
+ var infoBar = createInfoBar('Provision a Linux virtual machine on System z by selecting the appropriate choices below. Once you are ready, click on Provision to provision the virtual machine.');
+ provForm.append(infoBar);
+
+ // Append to provision tab
+ $('#' + tabId).append(provForm);
+
+ // Create provision table
+ var provTable = $(' zVM Group Image ');
+ var provBody = $(' ');
+ var provFooter = $(' ');
+ provTable.append(provHeader, provBody, provFooter);
+ provForm.append(provTable);
+
+ provHeader.children('th').css({
+ 'font': 'bold 12px verdana, arial, helvetica, sans-serif'
+ });
+
+ // Create row to contain selections
+ var provRow = $(' ');
+ provBody.append(provRow);
+ // Create columns for zVM, group, and image
+ var zvmCol = $(' ');
+ provRow.append(zvmCol);
+ var groupCol = $(' ');
+ provRow.append(groupCol);
+ var imageCol = $(' ');
+ provRow.append(imageCol);
+
+ provRow.children('td').css({
+ 'min-width': '250px'
+ });
+
+ /**
+ * Provision VM
+ */
+ var provisionBtn = createButton('Provision');
+ provisionBtn.bind('click', function(event) {
+ var hcp = $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]:checked').val();
+ var group = $('#select-table tbody tr:eq(0) td:eq(1) input[name="group"]:checked').val();
+ var img = $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]:checked').val();
+ var owner = $.cookie('srv_usrname');;
+
+ // Begin by creating VM
+ createVM(tabId, group, hcp, img, owner);
+ });
+ provForm.append(provisionBtn);
+}
+
+/**
+ * Create virtual machine
+ *
+ * @param tabId
+ * Tab ID
+ * @param group
+ * Group
+ * @param hcp
+ * Hardware control point
+ * @param img
+ * OS image
+ * @return Nothing
+ */
+function createVM(tabId, group, hcp, img, owner) {
+ var statBar = createStatusBar('provsionStatBar');
+ var loader = createLoader('provisionLoader');
+ statBar.find('div').append(loader);
+ statBar.prependTo($('#provisionTab'));
+
+ // Submit request to create VM
+ // webportal provzlinux [group] [hcp] [image] [owner]
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webportal',
+ tgt : '',
+ args : 'provzlinux;' + group + ';' + hcp + ';' + img + ';' + owner,
+ msg : ''
+ },
+ success:function(data){
+ $('#provisionLoader').remove();
+ for(var i in data.rsp){
+ $('#provsionStatBar').find('div').append('' + data.rsp[i] + ' ');
+ }
+
+ // Refresh nodes table
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ setUserNodes(data);
+ }
+ });
+ }
+ });
+}
+
+/**
+ * Load zVMs into column
+ */
+function loadzVMs() {
+ var zvmCol = $('#select-table tbody tr:eq(0) td:eq(0)');
+
+ // Get group names and description and append to group column
+ var groupNames = $.cookie('srv_zvms').split(',');
+ var radio, zvmBlock, args, zvm, hcp;
+ for (var i in groupNames) {
+ args = groupNames[i].split(':');
+ zvm = args[0];
+ hcp = args[1];
+
+ // Create block for each group
+ zvmBlock = $('
').css({
+ 'border': '1px solid',
+ 'max-width': '200px',
+ 'margin': '5px auto',
+ 'padding': '5px',
+ 'display': 'inline-block',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer'
+ }).click(function(){
+ $(this).children('input:radio').attr('checked', 'checked');
+ $(this).parents('td').find('div').attr('class', 'ui-state-default');
+ $(this).attr('class', 'ui-state-active');
+ });
+ radio = $(' ').css('display', 'none');
+ zvmBlock.append(radio, $('Name: ' + zvm + ' '), $('zHCP: ' + hcp + ' '));
+ zvmBlock.children('span').css({
+ 'display': 'block',
+ 'margin': '5px'
+ });
+ zvmCol.append(zvmBlock);
+ }
+}
+
+/**
+ * Load groups into column
+ */
+function loadGroups() {
+ var groupCol = $('#select-table tbody tr:eq(0) td:eq(1)');
+
+ // Get group names and description and append to group column
+ var groupNames = $.cookie('srv_groups').split(',');
+ var groupBlock, radio, args, name, ip, hostname, desc;
+ for (var i in groupNames) {
+ args = groupNames[i].split(':');
+ name = args[0];
+ ip = args[1];
+ hostname = args[2];
+ desc = args[3];
+
+ // Create block for each group
+ groupBlock = $('
').css({
+ 'border': '1px solid',
+ 'max-width': '200px',
+ 'margin': '5px auto',
+ 'padding': '5px',
+ 'display': 'inline-block',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer'
+ }).click(function(){
+ $(this).children('input:radio').attr('checked', 'checked');
+ $(this).parents('td').find('div').attr('class', 'ui-state-default');
+ $(this).attr('class', 'ui-state-active');
+ });
+ radio = $(' ').css('display', 'none');
+ groupBlock.append(radio, $('Name: ' + name + ' '), $('Description: ' + desc + ' '));
+ groupBlock.children('span').css({
+ 'display': 'block',
+ 'margin': '5px'
+ });
+ groupCol.append(groupBlock);
+ }
+}
+
+/**
+ * Load OS images into column
+ */
+function loadOSImages() {
+ var imgCol = $('#select-table tbody tr:eq(0) td:eq(2)');
+
+ // Get group names and description and append to group column
+ var imgNames = $.cookie('srv_imagenames').split(',');
+ var imgBlock, radio, args, name, desc;
+ for (var i in imgNames) {
+ args = imgNames[i].split(':');
+ name = args[0];
+ desc = args[1];
+
+ // Create block for each image
+ imgBlock = $('
').css({
+ 'border': '1px solid',
+ 'max-width': '200px',
+ 'margin': '5px auto',
+ 'padding': '5px',
+ 'display': 'inline-block',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer'
+ }).click(function(){
+ $(this).children('input:radio').attr('checked', 'checked');
+ $(this).parents('td').find('div').attr('class', 'ui-state-default');
+ $(this).attr('class', 'ui-state-active');
+ });
+ radio = $(' ').css('display', 'none');
+ imgBlock.append(radio, $('Name: ' + name + ' '), $('Description: ' + desc + ' '));
+ imgBlock.children('span').css({
+ 'display': 'block',
+ 'margin': '5px'
+ });
+ imgCol.append(imgBlock);
+ }
+}
+
+/**
+ * Set a cookie for zVM host names
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function setzVMCookies(data) {
+ if (data.rsp) {
+ var zvms = new Array();
+ for ( var i = 0; i < data.rsp.length; i++) {
+ zvms.push(data.rsp[i]);
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie('srv_zvms', zvms, { expires: exDate });
+ }
+}
+
+/**
+ * Set a cookie for disk pool names
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function setGroupCookies(data) {
+ if (data.rsp) {
+ var groups = new Array();
+
+ // Index 0 is the table header
+ var cols, name, ip, hostname, desc;
+ for ( var i = 1; i < data.rsp.length; i++) {
+ // Split into columns:
+ // node, ip, hostnames, otherinterfaces, comments, disable
+ cols = data.rsp[i].split(',');
+ name = cols[0].replace(new RegExp('"', 'g'), '');
+ ip = cols[1].replace(new RegExp('"', 'g'), '');
+ hostname = cols[2].replace(new RegExp('"', 'g'), '');
+ desc = cols[4].replace(new RegExp('"', 'g'), '');
+ groups.push(name + ':' + ip + ':' + hostname + ':' + desc);
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie('srv_groups', groups, { expires: exDate });
+ }
+}
+
+/**
+ * Set a cookie for the OS images
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function setOSImageCookies(data) {
+ // Get response
+ var rsp = data.rsp;
+
+ var imageNames = new Array;
+ var profilesHash = new Object();
+ var osVersHash = new Object();
+ var osArchsHash = new Object();
+ var imagePos = 0;
+ var profilePos = 0;
+ var osversPos = 0;
+ var osarchPos = 0;
+ var provMethodPos = 0;
+ var comments = 0;
+ // Get the column value
+ var colNameArray = rsp[0].substr(1).split(',');
+ for (var i in colNameArray){
+ switch (colNameArray[i]){
+ case 'imagename': {
+ imagePos = i;
+ }
+ break;
+
+ case 'profile':{
+ profilePos = i;
+ }
+ break;
+
+ case 'osvers':{
+ osversPos = i;
+ }
+ break;
+
+ case 'osarch':{
+ osarchPos = i;
+ }
+ break;
+
+ case 'comments':{
+ comments = i;
+ }
+ break;
+
+ case 'provmethod':{
+ provMethodPos = i;
+ }
+ break;
+
+ default :
+ break;
+ }
+ }
+
+ // Go through each index
+ for (var i = 1; i < rsp.length; i++) {
+ // Get image name
+ var cols = rsp[i].split(',');
+ var osImage = cols[imagePos].replace(new RegExp('"', 'g'), '');
+ var profile = cols[profilePos].replace(new RegExp('"', 'g'), '');
+ var provMethod = cols[provMethodPos].replace(new RegExp('"', 'g'), '');
+ var osVer = cols[osversPos].replace(new RegExp('"', 'g'), '');
+ var osArch = cols[osarchPos].replace(new RegExp('"', 'g'), '');
+ var osComments = cols[comments].replace(new RegExp('"', 'g'), '');
+
+ // Only save compute profile and install boot
+ if (profile.indexOf('compute') > -1 && provMethod.indexOf('install') > -1) {
+ if (!osComments)
+ osComments = 'No descritption';
+ imageNames.push(osImage + ':' + osComments);
+ profilesHash[profile] = 1;
+ osVersHash[osVer] = 1;
+ osArchsHash[osArch] = 1;
+ }
+
+
+ }
+
+ // Save image names in a cookie
+ $.cookie('srv_imagenames', imageNames);
+
+ // Save profiles in a cookie
+ var tmp = new Array;
+ for (var key in profilesHash) {
+ tmp.push(key);
+ }
+ $.cookie('srv_profiles', tmp);
+
+ // Save OS versions in a cookie
+ tmp = new Array;
+ for (var key in osVersHash) {
+ tmp.push(key);
+ }
+ $.cookie('srv_osvers', tmp);
+
+ // Save OS architectures in a cookie
+ tmp = new Array;
+ for (var key in osArchsHash) {
+ tmp.push(key);
+ }
+ $.cookie('srv_osarchs', tmp);
+}
+
+/**
+ * Set a cookie for disk pool names of a given node
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function setDiskPoolCookies(data) {
+ if (data.rsp) {
+ var node = data.msg;
+ var pools = data.rsp[0].split(node + ': ');
+ for (var i in pools) {
+ pools[i] = jQuery.trim(pools[i]);
+ }
+
+ // Set cookie to expire in 60 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie(node + 'diskpools', pools, { expires: exDate });
+ }
+}
+
+/**
+ * Set a cookie for user nodes
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function setUserNodes(data) {
+ if (data.rsp) {
+ // Get user name that is logged in
+ var userName = $.cookie('srv_usrname');
+ var usrNodes = new Array();
+
+ // Ignore first columns because it is the header
+ for ( var i = 1; i < data.rsp.length; i++) {
+ // Go through each column
+ // where column names are: node, os, arch, profile, provmethod, supportedarchs, nodetype, comments, disable
+ var cols = data.rsp[i].split(',');
+ var node = cols[0].replace(new RegExp('"', 'g'), '');
+ var owner = cols[7].replace(new RegExp('"', 'g'), '');
+ owner = owner.replace('owner:', '');
+
+ if (owner == userName) {
+ usrNodes.push(node);
+ }
+ } // End of for
+
+ // Set cookie to expire in 240 minutes
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie(userName + '_usrnodes', usrNodes, { expires: exDate });
+ } // End of if
+}
+
+/**
+ * Power on a given node
+ *
+ * @param node
+ * Node to power on or off
+ * @param power2
+ * Power node to given state
+ * @return Nothing
+ */
+function powerNode(node, power2) {
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rpower',
+ tgt : node,
+ args : power2,
+ msg : node
+ },
+
+ success : updatePowerStatus
+ });
+}
+
+/**
+ * Update power status of a node in the datatable
+ *
+ * @param data
+ * Data from HTTP request
+ * @return Nothing
+ */
+function updatePowerStatus(data) {
+ // Get datatable
+ var nodesDTId = 'userNodesDT';
+ var dTable = $('#' + nodesDTId).dataTable();
+
+ // Get xCAT response
+ var rsp = data.rsp;
+ // Loop through each line
+ var node, status, rowPos, strPos;
+ for (var i in rsp) {
+ // Get node name
+ node = rsp[i].split(":")[0];
+
+ // If there is no error
+ if (rsp[i].indexOf("Error") < 0 || rsp[i].indexOf("Failed") < 0) {
+ // Get the row containing the node link
+ rowPos = findRow(node, '#' + nodesDTId, 1);
+
+ // If it was power on, then the data return would contain "Starting"
+ strPos = rsp[i].indexOf("Starting");
+ if (strPos > -1) {
+ status = 'on';
+ } else {
+ status = 'off';
+ }
+
+ // Update the power status column
+ dTable.fnUpdate(status, rowPos, 3, false);
+ } else {
+ // Power on/off failed
+ alert(rsp[i]);
+ }
+ }
+}
+
+/**
+ * Turn on monitoring for a given node
+ *
+ * @param node
+ * Node to monitor on or off
+ * @param monitor
+ * Monitor state, on or off
+ * @return Nothing
+ */
+function monitorNode(node, monitor) {
+ if (monitor == 'on') {
+ // Append loader to warning bar
+ var gangliaLoader = createLoader('');
+ var warningBar = $('#nodesTab').find('.ui-state-error p');
+ if (warningBar.length) {
+ warningBar.append(gangliaLoader);
+ }
+
+ if (node) {
+ // Check if ganglia RPMs are installed
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacheck;' + node,
+ msg : node // Node range will be passed along in data.msg
+ },
+
+ /**
+ * Start ganglia on a given node range
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+ success : function(data) {
+ // Get response
+ var out = data.rsp[0].split(/\n/);
+
+ // Go through each line
+ var warn = false;
+ var warningMsg = '';
+ for (var i in out) {
+ // If an RPM is not installed
+ if (out[i].indexOf('not installed') > -1) {
+ warn = true;
+
+ if (warningMsg) {
+ warningMsg += ' ' + out[i];
+ } else {
+ warningMsg = out[i];
+ }
+ }
+ }
+
+ // If there are warnings
+ if (warn) {
+ // Create warning bar
+ var warningBar = createWarnBar(warningMsg);
+ warningBar.css('margin-bottom', '10px');
+ warningBar.prependTo($('#nodesTab'));
+ } else {
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliastart;' + data.msg,
+ msg : data.msg
+ },
+
+ success : function(data) {
+ // Remove any warnings
+ $('#nodesTab').find('.ui-state-error').remove();
+ refreshGangliaStatus(data.msg);
+ }
+ });
+ } // End of if (warn)
+ } // End of function(data)
+ });
+ }
+ } else {
+ var args;
+ if (node) {
+ args = 'gangliastop;' + node;
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : args,
+ msg : node
+ },
+
+ success : function(data) {
+ refreshGangliaStatus(data.msg);
+ }
+ });
+ }
+ }
+}
+
+/**
+ * Open a dialog to delete node
+ *
+ * @param tgtNodes
+ * Nodes to delete
+ * @return Nothing
+ */
+function deleteNode(tgtNodes) {
+ var nodes = tgtNodes.split(',');
+
+ // Loop through each node and create target nodes string
+ var tgtNodesStr = '';
+ for (var i in nodes) {
+ if (i == 0 && i == nodes.length - 1) {
+ // If it is the 1st and only node
+ tgtNodesStr += nodes[i];
+ } else if (i == 0 && i != nodes.length - 1) {
+ // If it is the 1st node of many nodes, append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ if (i == nodes.length - 1) {
+ // If it is the last node, append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ // Confirm delete
+ var confirmMsg = $('Are you sure you want to delete ' + tgtNodesStr + '?
').css({
+ 'display': 'inline',
+ 'margin': '5px',
+ 'vertical-align': 'middle',
+ 'word-wrap': 'break-word'
+ });
+
+ var style = {
+ 'display': 'inline-block',
+ 'margin': '5px',
+ 'vertical-align': 'middle'
+ };
+
+ var dialog = $('
');
+ var icon = $(' ').css(style);
+ dialog.append(icon);
+ dialog.append(confirmMsg);
+
+ // Open dialog
+ dialog.dialog({
+ title: "Confirm",
+ modal: true,
+ width: 400,
+ buttons: {
+ "Yes": function(){
+ // Create status bar and append to tab
+ var instance = 0;
+ var statBarId = 'deleteStat' + instance;
+ while ($('#' + statBarId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ statBarId = 'deleteStat' + instance;
+ }
+
+ var statBar = createStatusBar(statBarId);
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+ statBar.prependTo($('#manageTab'));
+
+ // Delete the virtual server
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'rmvm',
+ tgt : tgtNodes,
+ args : '',
+ msg : 'out=' + statBarId + ';cmd=rmvm;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ var args = data.msg.split(';');
+ var statBarId = args[0].replace('out=', '');
+ var tgts = args[2].replace('tgt=', '').split(',');
+
+ // Get data table
+ var nodesDTId = 'userNodesDT';
+ var dTable = $('#' + nodesDTId).dataTable();
+ var failed = false;
+
+ // Create an info box to show output
+ var output = writeRsp(data.rsp, '');
+ output.css('margin', '0px');
+ // Remove loader and append output
+ $('#' + statBarId + ' img').remove();
+ $('#' + statBarId + ' div').append(output);
+
+ // If there was an error, do not continue
+ if (output.html().indexOf('Error') > -1) {
+ failed = true;
+ }
+
+ // Update data table
+ var rowPos;
+ for (var i in tgts) {
+ if (!failed) {
+ // Get row containing the node link and delete it
+ rowPos = findRow(tgts[i], '#' + nodesDTId, 1);
+ dTable.fnDeleteRow(rowPos);
+ }
+ }
+
+ // Refresh nodes owned by user
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'tabdump',
+ tgt : '',
+ args : 'nodetype',
+ msg : ''
+ },
+
+ success : function(data) {
+ setUserNodes(data);
+ }
+ });
+ }
+ });
+
+ $(this).dialog("close");
+ },
+ "No": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Unlock a node by setting the ssh keys
+ *
+ * @param tgtNodes
+ * Nodes to unlock
+ * @return Nothing
+ */
+function unlockNode(tgtNodes) {
+ var nodes = tgtNodes.split(',');
+
+ // Loop through each node and create target nodes string
+ var tgtNodesStr = '';
+ for (var i in nodes) {
+ if (i == 0 && i == nodes.length - 1) {
+ // If it is the 1st and only node
+ tgtNodesStr += nodes[i];
+ } else if (i == 0 && i != nodes.length - 1) {
+ // If it is the 1st node of many nodes, append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ } else {
+ if (i == nodes.length - 1) {
+ // If it is the last node, append nothing to the string
+ tgtNodesStr += nodes[i];
+ } else {
+ // Append a comma to the string
+ tgtNodesStr += nodes[i] + ', ';
+ }
+ }
+ }
+
+ var dialog = $('
');
+ var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.');
+ dialog.append(infoBar);
+
+ var unlockForm = $('
').css('margin', '5px');
+ unlockForm.append('Target node range:
');
+ unlockForm.append('Password:
');
+ dialog.append(unlockForm);
+
+ dialog.find('div input').css('margin', '5px');
+
+ // Generate tooltips
+ unlockForm.find('div input[title]').tooltip({
+ position: "center right",
+ offset: [-2, 10],
+ effect: "fade",
+ opacity: 0.7,
+ predelay: 800,
+ events : {
+ def : "mouseover,mouseout",
+ input : "mouseover,mouseout",
+ widget : "focus mouseover,blur mouseout",
+ tooltip : "mouseover,mouseout"
+ }
+ });
+
+ // Open dialog
+ dialog.dialog({
+ title: "Confirm",
+ modal: true,
+ width: 450,
+ buttons: {
+ "Ok": function(){
+ // Create status bar and append to tab
+ var instance = 0;
+ var statBarId = 'unlockStat' + instance;
+ while ($('#' + statBarId).length) {
+ // If one already exists, generate another one
+ instance = instance + 1;
+ statBarId = 'unlockStat' + instance;
+ }
+
+ var statBar = createStatusBar(statBarId);
+ var loader = createLoader('');
+ statBar.find('div').append(loader);
+ statBar.prependTo($('#manageTab'));
+
+ // If a password is given
+ var password = unlockForm.find('input[name=password]:eq(0)');
+ if (password.val()) {
+ // Setup SSH keys
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'unlock;' + tgtNodes + ';' + password.val(),
+ msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes
+ },
+
+ success : function(data) {
+ // Create an info box to show output
+ var output = writeRsp(data.rsp, '');
+ output.css('margin', '0px');
+ // Remove loader and append output
+ $('#' + statBarId + ' img').remove();
+ $('#' + statBarId + ' div').append(output);
+ }
+ });
+
+ $(this).dialog("close");
+ }
+ },
+ "Cancel": function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Get nodes current load information
+ */
+function getNodesCurrentLoad(){
+ var userName = $.cookie('srv_usrname');
+ var nodes = $.cookie(userName + '_usrnodes');
+
+ // Get nodes current status
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliacurrent;node;' + nodes,
+ msg : ''
+ },
+
+ success: saveNodeLoad
+ });
+}
+
+/**
+ * Save node load data
+ *
+ * @param status
+ * Data returned from HTTP request
+ */
+function saveNodeLoad(status){
+ // Save node path and status for future use
+ nodePath = new Object();
+ nodeStatus = new Object();
+
+ // Get nodes status
+ var nodes = status.rsp[0].split(';');
+
+ var i = 0, pos = 0;
+ var node = '', tmpStr = '';
+ var tmpArry;
+
+ for (i = 0; i < nodes.length; i++){
+ tmpStr = nodes[i];
+ pos = tmpStr.indexOf(':');
+ node = tmpStr.substring(0, pos);
+ tmpArry = tmpStr.substring(pos + 1).split(',');
+
+ switch(tmpArry[0]){
+ case 'UNKNOWN':{
+ nodeStatus[node] = -2;
+ }
+ break;
+ case 'ERROR':{
+ nodeStatus[node] = -1;
+ }
+ break;
+ case 'WARNING':{
+ nodeStatus[node] = 0;
+ nodePath[node] = tmpArry[1];
+ }
+ break;
+ case 'NORMAL':{
+ nodeStatus[node] = 1;
+ nodePath[node] = tmpArry[1];
+ }
+ break;
+ }
+ }
+}
+
+/**
+ * Get monitoring metrics and load into inventory fieldset
+ *
+ * @param node
+ * Node to collect metrics
+ * @return Nothing
+ */
+function getMonitorMetrics(node) {
+ $('#' + node + '_monitor').children().remove();
+
+ // Get monitoring metrics
+ $.ajax({
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'webrun',
+ tgt : '',
+ args : 'gangliashow;' + nodePath[node] + ';hour;_summary_',
+ msg : node
+ },
+
+ success: drawMonitoringCharts
+ });
+}
+
+/**
+ * Draw monitoring charts based on node metrics
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+function drawMonitoringCharts(data){
+ var nodeMetrics = new Object();
+ var metricData = data.rsp[0].split(';');
+ var node = data.msg;
+
+ var metricName = '';
+ var metricVal = '';
+ var pos = 0;
+
+ // Go through the metrics returned
+ for (var m = 0; m < metricData.length; m++){
+ pos = metricData[m].indexOf(':');
+
+ // Get metric name
+ metricName = metricData[m].substr(0, pos);
+ nodeMetrics[metricName] = new Array();
+ // Get metric values
+ metricVal = metricData[m].substr(pos + 1).split(',');
+ // Save node metrics
+ for (var i = 0; i < metricVal.length; i++){
+ nodeMetrics[metricName].push(Number(metricVal[i]));
+ }
+ }
+
+ drawLoadFlot(node, nodeMetrics['load_one'], nodeMetrics['cpu_num']);
+ drawCpuFlot(node, nodeMetrics['cpu_idle']);
+ drawMemFlot(node, nodeMetrics['mem_free'], nodeMetrics['mem_total']);
+ drawDiskFlot(node, nodeMetrics['disk_free'], nodeMetrics['disk_total']);
+ drawNetworkFlot(node, nodeMetrics['bytes_in'], nodeMetrics['bytes_out']);
+}
+
+/**
+ * Draw load metrics flot
+ *
+ * @param node
+ * Node name
+ * @param loadpair
+ * Load timestamp and value pair
+ * @param cpupair
+ * CPU number and value pair
+ * @return Nothing
+ */
+function drawLoadFlot(node, loadPair, cpuPair){
+ var load = new Array();
+ var cpu = new Array();
+
+ var i = 0;
+ var yAxisMax = 0;
+ var interval = 1;
+
+ // Append flot to node monitoring fieldset
+ var loadFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(loadFlot);
+ $('#' + node + '_load').empty();
+
+ // Parse load pair where:
+ // timestamp must be mutiplied by 1000 and Javascript timestamp is in ms
+ for (i = 0; i < loadPair.length; i += 2){
+ load.push([loadPair[i] * 1000, loadPair[i + 1]]);
+ if (loadPair[i + 1] > yAxisMax){
+ yAxisMax = loadPair[i + 1];
+ }
+ }
+
+ // Parse CPU pair
+ for (i = 0; i < cpuPair.length; i += 2){
+ cpu.push([cpuPair[i] * 1000, cpuPair[i + 1]]);
+ if (cpuPair[i + 1] > yAxisMax){
+ yAxisMax = cpuPair[i + 1];
+ }
+ }
+
+ interval = parseInt(yAxisMax / 3);
+ if (interval < 1){
+ interval = 1;
+ }
+
+ $.jqplot(node + '_load', [load, cpu],{
+ title: ' Loads/Procs Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickInterval : interval
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Load'}, {label: 'CPU Number'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw CPU usage flot
+ *
+ * @param node
+ * Node name
+ * @param cpuPair
+ * CPU timestamp and value pair
+ * @return Nothing
+ */
+function drawCpuFlot(node, cpuPair){
+ var cpu = new Array();
+
+ // Append flot to node monitoring fieldset
+ var cpuFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(cpuFlot);
+ $('#' + node + '_cpu').empty();
+
+ // Time stamp should by mutiplied by 1000
+ // CPU idle comes from server, subtract 1 from idle
+ for(var i = 0; i < cpuPair.length; i +=2){
+ cpu.push([(cpuPair[i] * 1000), (100 - cpuPair[i + 1])]);
+ }
+
+ $.jqplot(node + '_cpu', [cpu],{
+ title: 'CPU Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ max : 100,
+ tickOptions:{formatString : '%d\%'}
+ }
+ },
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw memory usage flot
+ *
+ * @param node
+ * Node name
+ * @param freePair
+ * Free memory timestamp and value pair
+ * @param totalPair
+ * Total memory timestamp and value pair
+ * @return Nothing
+ */
+function drawMemFlot(node, freePair, totalPair){
+ var used = new Array();
+ var total = new Array();
+ var size = 0;
+
+ // Append flot to node monitoring fieldset
+ var memoryFlot = $('
').css({
+ 'float': 'left',
+ 'height': '150px',
+ 'margin': '0 0 10px',
+ 'width': '300px'
+ });
+ $('#' + node + '_monitor').append(memoryFlot);
+ $('#' + node + '_memory').empty();
+
+ if(freePair.length < totalPair.length){
+ size = freePair.length;
+ } else {
+ size = freePair.length;
+ }
+
+ var tmpTotal, tmpUsed;
+ for(var i = 0; i < size; i+=2){
+ tmpTotal = totalPair[i+1];
+ tmpUsed = tmpTotal-freePair[i+1];
+ tmpTotal = tmpTotal/1000000;
+ tmpUsed = tmpUsed/1000000;
+ total.push([totalPair[i]*1000, tmpTotal]);
+ used.push([freePair[i]*1000, tmpUsed]);
+ }
+
+ $.jqplot(node + '_memory', [used, total],{
+ title: 'Memory Use Last Hour',
+ axes:{
+ xaxis:{
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks: 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis: {
+ min : 0,
+ tickOptions:{formatString : '%.2fG'}
+ }
+ },
+ legend : {
+ show: true,
+ location: 'nw'
+ },
+ series:[{label:'Used'}, {label: 'Total'}],
+ seriesDefaults : {showMarker: false}
+ });
+}
+
+/**
+ * Draw disk usage flot
+ *
+ * @param node
+ * Node name
+ * @param freePair
+ * Free disk space (Ganglia only logs free data)
+ * @param totalPair
+ * Total disk space
+ * @return Nothing
+ */
+function drawDiskFlot(node, freePair, totalPair) {
+ var used = new Array();
+ var total = new Array();
+ var size = 0;
+
+ // Append flot to node monitoring fieldset
+ var diskFlot = $('
').css({
+ 'float' : 'left',
+ 'height' : '150px',
+ 'margin' : '0 0 10px',
+ 'width' : '300px'
+ });
+ $('#' + node + '_monitor').append(diskFlot);
+ $('#' + node + '_disk').empty();
+
+ if (freePair.length < totalPair.length) {
+ size = freePair.length;
+ } else {
+ size = freePair.length;
+ }
+
+ var tmpTotal, tmpUsed;
+ for ( var i = 0; i < size; i += 2) {
+ tmpTotal = totalPair[i + 1];
+ tmpUsed = tmpTotal - freePair[i + 1];
+ total.push([ totalPair[i] * 1000, tmpTotal ]);
+ used.push([ freePair[i] * 1000, tmpUsed ]);
+ }
+
+ $.jqplot(node + '_disk', [ used, total ], {
+ title : 'Disk Use Last Hour',
+ axes : {
+ xaxis : {
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis : {
+ min : 0,
+ tickOptions : {
+ formatString : '%.2fG'
+ }
+ }
+ },
+ legend : {
+ show : true,
+ location : 'nw'
+ },
+ series : [ {
+ label : 'Used'
+ }, {
+ label : 'Total'
+ } ],
+ seriesDefaults : {
+ showMarker : false
+ }
+ });
+}
+
+/**
+ * Draw network usage flot
+ *
+ * @param node
+ * Node name
+ * @param freePair
+ * Free memory timestamp and value pair
+ * @param totalPair
+ * Total memory timestamp and value pair
+ * @return Nothing
+ */
+function drawNetworkFlot(node, inPair, outPair) {
+ var inArray = new Array();
+ var outArray = new Array();
+ var maxVal = 0;
+ var unitName = 'B';
+ var divisor = 1;
+
+ // Append flot to node monitoring fieldset
+ var diskFlot = $('
').css({
+ 'float' : 'left',
+ 'height' : '150px',
+ 'margin' : '0 0 10px',
+ 'width' : '300px'
+ });
+ $('#' + node + '_monitor').append(diskFlot);
+ $('#' + node + '_network').empty();
+
+ for (var i = 0; i < inPair.length; i += 2) {
+ if (inPair[i + 1] > maxVal) {
+ maxVal = inPair[i + 1];
+ }
+ }
+
+ for (var i = 0; i < outPair.length; i += 2) {
+ if (outPair[i + 1] > maxVal) {
+ maxVal = outPair[i + 1];
+ }
+ }
+
+ if (maxVal > 3000000) {
+ divisor = 1000000;
+ unitName = 'GB';
+ } else if (maxVal >= 3000) {
+ divisor = 1000;
+ unitName = 'MB';
+ } else {
+ // Do nothing
+ }
+
+ for (i = 0; i < inPair.length; i += 2) {
+ inArray.push([ (inPair[i] * 1000), (inPair[i + 1] / divisor) ]);
+ }
+
+ for (i = 0; i < outPair.length; i += 2) {
+ outArray.push([ (outPair[i] * 1000), (outPair[i + 1] / divisor) ]);
+ }
+
+ $.jqplot(node + '_network', [ inArray, outArray ], {
+ title : 'Network Last Hour',
+ axes : {
+ xaxis : {
+ renderer : $.jqplot.DateAxisRenderer,
+ numberTicks : 4,
+ tickOptions : {
+ formatString : '%R',
+ show : true
+ }
+ },
+ yaxis : {
+ min : 0,
+ tickOptions : {
+ formatString : '%d' + unitName
+ }
+ }
+ },
+ legend : {
+ show : true,
+ location : 'nw'
+ },
+ series : [ {
+ label : 'In'
+ }, {
+ label : 'Out'
+ } ],
+ seriesDefaults : {
+ showMarker : false
+ }
+ });
+}
\ No newline at end of file
diff --git a/xCAT-UI/js/service/utils.js b/xCAT-UI/js/service/utils.js
new file mode 100644
index 000000000..557e795c4
--- /dev/null
+++ b/xCAT-UI/js/service/utils.js
@@ -0,0 +1,321 @@
+/**
+ * Get nodes currently shown in datatable
+ *
+ * @param tableId
+ * Datatable ID
+ * @return String of nodes shown
+ */
+function getNodesShown(tableId) {
+ // String of nodes shown
+ var shownNodes = '';
+
+ // Get rows of shown nodes
+ var nodes = $('#' + tableId + ' tbody tr');
+
+ // Go through each row
+ var cols;
+ for (var i = 0; i < nodes.length; i++) {
+ // Get second column containing node name
+ cols = nodes.eq(i).find('td');
+ shownNodes += cols.eq(1).text() + ',';
+ }
+
+ // Remove last comma
+ shownNodes = shownNodes.substring(0, shownNodes.length-1);
+ return shownNodes;
+}
+
+/**
+ * Find the row index containing a column with a given string
+ *
+ * @param str
+ * String to search for
+ * @param table
+ * Table to check
+ * @param col
+ * Column to find string under
+ * @return The row index containing the search string
+ */
+function findRow(str, table, col){
+ var dTable, rows;
+
+ // Get datatable
+ dTable = $(table).dataTable();
+ rows = dTable.fnGetData();
+
+ // Loop through each row
+ for (var i in rows) {
+ // If the column contains the search string
+ if (rows[i][col].indexOf(str) > -1) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Select all checkboxes in the datatable
+ *
+ * @param event
+ * Event on element
+ * @param obj
+ * Object triggering event
+ * @return Nothing
+ */
+function selectAll(event, obj) {
+ var status = obj.attr('checked');
+ var checkboxes = obj.parents('.dataTables_scroll').find('.dataTables_scrollBody input:checkbox');
+ if (status) {
+ checkboxes.attr('checked', true);
+ } else {
+ checkboxes.attr('checked', false);
+ }
+
+ event.stopPropagation();
+}
+
+/**
+ * Get node attributes from HTTP request data
+ *
+ * @param propNames
+ * Hash table of property names
+ * @param keys
+ * Property keys
+ * @param data
+ * Data from HTTP request
+ * @return Hash table of property values
+ */
+function getAttrs(keys, propNames, data) {
+ // Create hash table for property values
+ var attrs = new Object();
+
+ // Go through inventory and separate each property out
+ var curKey; // Current property key
+ var addLine; // Add a line to the current property?
+ for ( var i = 1; i < data.length; i++) {
+ addLine = true;
+
+ // Loop through property keys
+ // Does this line contains one of the properties?
+ for ( var j = 0; j < keys.length; j++) {
+ // Find property name
+ if (data[i].indexOf(propNames[keys[j]]) > -1) {
+ attrs[keys[j]] = new Array();
+
+ // Get rid of property name in the line
+ data[i] = data[i].replace(propNames[keys[j]], '');
+ // Trim the line
+ data[i] = jQuery.trim(data[i]);
+
+ // Do not insert empty line
+ if (data[i].length > 0) {
+ attrs[keys[j]].push(data[i]);
+ }
+
+ curKey = keys[j];
+ addLine = false; // This line belongs to a property
+ }
+ }
+
+ // Line does not contain a property
+ // Must belong to previous property
+ if (addLine && data[i].length > 1) {
+ data[i] = jQuery.trim(data[i]);
+ attrs[curKey].push(data[i]);
+ }
+ }
+
+ return attrs;
+}
+
+/**
+ * Create a tool tip for comments
+ *
+ * @param comment
+ * Comments to be placed in a tool tip
+ * @return Tool tip
+ */
+function createCommentsToolTip(comment) {
+ // Create tooltip container
+ var toolTip = $('
');
+ // Create textarea to hold comment
+ var txtArea = $('').css({
+ 'font-size': '10px',
+ 'height': '50px',
+ 'width': '200px',
+ 'background-color': '#000',
+ 'color': '#fff',
+ 'border': '0px',
+ 'display': 'block'
+ });
+
+ // Create links to save and cancel changes
+ var lnkStyle = {
+ 'color': '#58ACFA',
+ 'font-size': '10px',
+ 'display': 'inline-block',
+ 'padding': '5px',
+ 'float': 'right'
+ };
+
+ var saveLnk = $('Save ').css(lnkStyle).hide();
+ var cancelLnk = $('Cancel ').css(lnkStyle).hide();
+ var infoSpan = $('Click to edit ').css(lnkStyle);
+
+ // Save changes onclick
+ saveLnk.bind('click', function(){
+ // Get node and comment
+ var node = $(this).parent().parent().find('img').attr('id').replace('Tip', '');
+ var comments = $(this).parent().find('textarea').val();
+
+ // Save comment
+ $.ajax( {
+ url : 'lib/srv_cmd.php',
+ dataType : 'json',
+ data : {
+ cmd : 'chdef',
+ tgt : '',
+ args : '-t;node;-o;' + node + ';usercomment=' + comments,
+ msg : 'out=manageTab;tgt=' + node
+ },
+
+ success: showChdefOutput
+ });
+
+ // Hide cancel and save links
+ $(this).hide();
+ cancelLnk.hide();
+ });
+
+ // Cancel changes onclick
+ cancelLnk.bind('click', function(){
+ // Get original comment and put it back
+ var orignComments = $(this).parent().find('textarea').text();
+ $(this).parent().find('textarea').val(orignComments);
+
+ // Hide cancel and save links
+ $(this).hide();
+ saveLnk.hide();
+ infoSpan.show();
+ });
+
+ // Show save link when comment is edited
+ txtArea.bind('click', function(){
+ saveLnk.show();
+ cancelLnk.show();
+ infoSpan.hide();
+ });
+
+ toolTip.append(txtArea);
+ toolTip.append(cancelLnk);
+ toolTip.append(saveLnk);
+ toolTip.append(infoSpan);
+
+ return toolTip;
+}
+
+/**
+ * Open a dialog and show given message
+ *
+ * @param type
+ * Type of dialog, i.e. warn or info
+ * @param msg
+ * Message to show
+ * @return Nothing
+ */
+function prompt(type, msg) {
+ var style = {
+ 'display': 'inline-block',
+ 'margin': '5px',
+ 'vertical-align': 'middle'
+ };
+ msg.css({
+ 'display': 'inline',
+ 'margin': '5px',
+ 'vertical-align': 'middle'
+ });
+
+ // Append icon
+ var icon;
+ var dialog = $('
');
+ if (type == "Warning") {
+ icon = $(' ').css(style);
+ } else {
+ icon = $(' ').css(style);
+ }
+
+ dialog.append(icon);
+ dialog.append(msg);
+
+ // Open dialog
+ dialog.dialog({
+ title: type,
+ modal: true,
+ width: 400,
+ buttons: {
+ "Ok": function(){
+ $(this).dialog("close");
+ }
+ }
+ });
+}
+
+/**
+ * Get nodes that are checked in a given datatable
+ *
+ * @param dTableId
+ * The datatable ID
+ * @return Nodes that were checked
+ */
+function getNodesChecked(dTableId) {
+ var tgts = '';
+
+ // Get nodes that were checked
+ var nodes = $('#' + dTableId + ' input[type=checkbox]:checked');
+ for (var i in nodes) {
+ var tgtNode = nodes.eq(i).attr('name');
+
+ if (tgtNode){
+ tgts += tgtNode;
+
+ // Add a comma at the end
+ if (i < nodes.length - 1) {
+ tgts += ',';
+ }
+ }
+ }
+
+ return tgts;
+}
+
+/**
+ * Show chdef output
+ *
+ * @param data
+ * Data returned from HTTP request
+ * @return Nothing
+ */
+function showChdefOutput(data) {
+ // Get output
+ var out = data.rsp;
+ var args = data.msg.split(';');
+ var tabID = args[0].replace('out=', '');
+ var tgt = args[1].replace('tgt=', '');
+
+ // Find info bar on nodes tab, if any
+ var info = $('#' + tabID).find('.ui-state-highlight');
+ if (!info.length) {
+ // Create info bar if one does not exist
+ info = createInfoBar('');
+ $('#' + tabID).append(info);
+ }
+
+ // Go through output and append to paragraph
+ var prg = $('
');
+ for (var i in out) {
+ prg.append(tgt + ': ' + out[i] + ' ');
+ }
+
+ info.append(prg);
+}
\ No newline at end of file
diff --git a/xCAT-UI/js/srv_xcatauth.js b/xCAT-UI/js/srv_xcatauth.js
new file mode 100644
index 000000000..d0ea19c74
--- /dev/null
+++ b/xCAT-UI/js/srv_xcatauth.js
@@ -0,0 +1,90 @@
+/**
+ * Open login dialog
+ */
+$(document).ready(function() {
+ $('#header').remove();
+ $('#content').remove();
+
+ var winHeight = document.body.clientHeight;
+ var diagHeight = $('#logdialog').css('height');
+ diagHeight = diagHeight.substr(0, diagHeight.length - 2);
+ diagHeight = Number(diagHeight);
+
+ // The window's height is to small to show the dialog
+ var tmpHeight = 0;
+ if ((winHeight - 50) < diagHeight){
+ tmpHeight = 0;
+ } else {
+ tmpHeight = parseInt((winHeight - diagHeight - 50) / 2);
+ }
+
+ $('#logdialog').css('margin', tmpHeight + 'px auto');
+ $('button').bind('click', function(){
+ authenticate();
+ }).button();
+
+ if (document.location.protocol == 'http:') {
+ $('#logstatus').html('You are using an unencrypted session!');
+ $('#logstatus').css('color', 'red');
+ }
+
+ if (!$('#username').val()) {
+ $('#username').focus();
+ } else {
+ $('#password').focus();
+ }
+
+ // When enter is hit while in username, advance to password
+ $('#username').keydown(function(event) {
+ if (event.keyCode == 13) {
+ $('#password').focus();
+ }
+ });
+
+ // Submit authentication if enter is pressed in password field
+ $('#password').keydown(function(event) {
+ if (event.keyCode == 13) {
+ authenticate();
+ }
+ });
+});
+
+/**
+ * Update login dialog
+ *
+ * @param data
+ * Data returned from AJAX call
+ * @param txtStatus
+ * Status of login
+ */
+function onlogin(data, txtStatus) {
+ // Clear password field regardless of what happens
+ var usrName = $('#username').val();
+ $('#password').val('');
+ if (data.authenticated == 'yes') {
+ $('#logstatus').text('Login successful');
+ window.location = 'service.php';
+
+ // Set user name cookie
+ var exDate = new Date();
+ exDate.setTime(exDate.getTime() + (240 * 60 * 1000));
+ $.cookie('srv_usrname', usrName, { expires: exDate });
+ } else {
+ $('#logstatus').text('Authentication failure');
+ $('#logstatus').css('color', '#FF0000');
+ }
+}
+
+/**
+ * Authenticate user for new session
+ */
+function authenticate() {
+ $('#logstatus').css('color', '#000000');
+ $('#logstatus').html('Authenticating...');
+
+ var passwd = $('#password').val();
+ $.post('lib/srv_log.php', {
+ username : $('#username').val(),
+ password : passwd
+ }, onlogin, 'json');
+}
diff --git a/xCAT-UI/lib/srv_cmd.php b/xCAT-UI/lib/srv_cmd.php
new file mode 100644
index 000000000..3798fab27
--- /dev/null
+++ b/xCAT-UI/lib/srv_cmd.php
@@ -0,0 +1,192 @@
+children() as $child) {
+ foreach ($child->children() as $data) {
+ if($data->name) {
+ $node = $data->name;
+
+ if($data->data->contents){
+ $cont = $data->data->contents;
+ }
+ else{
+ $cont = $data->data;
+ }
+
+ $cont = str_replace(":|:", "\n", $cont);
+ array_push($rsp, "$node: $cont");
+ } else if(strlen("$data") > 2) {
+ $data = str_replace(":|:", "\n", $data);
+ array_push($rsp, "$data");
+ }
+ }
+ }
+ }
+
+ // Reply in the form of JSON
+ $rtn = array("rsp" => $rsp, "msg" => $msg);
+ echo json_encode($rtn);
+}
+
+/**
+ * Extract the output for a webrun command
+ *
+ * @param $xml The XML output from docmd()
+ * @return An array containing the output
+ */
+function extractWebrun($xml) {
+ $rsp = array();
+ $i = 0;
+
+ // Extract data returned
+ foreach($xml->children() as $nodes){
+ foreach($nodes->children() as $node){
+ // Get the node name
+ $name = $node->name;
+
+ // Get the content
+ $status = $node->data;
+ $status = str_replace(":|:", "\n", $status);
+
+ // Add to return array
+ $rsp[$i] = array("$name", "$status");
+ $i++;
+ }
+ }
+
+ return $rsp;
+}
+
+/**
+ * Extract the output for a nodels command
+ *
+ * @param $xml The XML output from docmd()
+ * @return An array containing the output
+ */
+function extractNodels($xml) {
+ $rsp = array();
+ $i = 0;
+
+ // Extract data returned
+ foreach($xml->children() as $nodes){
+ foreach($nodes->children() as $node){
+ // Get the node name
+ $name = $node->name;
+ // Get the content
+ $status = $node->data->contents;
+ $status = str_replace(":|:", "\n", $status);
+
+ $description = $node->data->desc;
+ // Add to return array
+ $rsp[$i] = array("$name", "$status", "$description");
+ $i++;
+ }
+ }
+
+ return $rsp;
+}
+
+/**
+ * Extract the output for a extnoderange command
+ *
+ * @param $xml The XML output from docmd()
+ * @return The nodes and groups
+ */
+function extractExtnoderange($xml) {
+ $rsp = array();
+
+ // Extract data returned
+ foreach ($xml->xcatresponse->intersectinggroups as $group) {
+ array_push($rsp, "$group");
+ }
+
+ return $rsp;
+}
+?>
\ No newline at end of file
diff --git a/xCAT-UI/lib/srv_functions.php b/xCAT-UI/lib/srv_functions.php
new file mode 100644
index 000000000..e2eb01a3a
--- /dev/null
+++ b/xCAT-UI/lib/srv_functions.php
@@ -0,0 +1,324 @@
+You are not logged in! Failed to run command.
";
+ return simplexml_load_string(' ', 'SimpleXMLElement', LIBXML_NOCDATA);
+ }
+
+ // Create xCAT request
+ // Add command, node range, and arguments to request
+ $request = simplexml_load_string(' ');
+ $request->addChild('command', $cmd);
+ if(!empty($nr)) { $request->addChild('noderange', $nr); }
+ if (!empty($args_array)) {
+ foreach ($args_array as $a) {
+ $request->addChild('arg',$a);
+ }
+ }
+
+ // Add user and password to request
+ $usernode=$request->addChild('becomeuser');
+ $usernode->addChild('username',$_SESSION["srv_username"]);
+ $usernode->addChild('password',getpassword());
+
+ $xml = submit_request($request, 0, $opts_array);
+ return $xml;
+}
+
+/**
+ * Used by docmd() to submit request to xCAT
+ *
+ * @param $req Tree of SimpleXML objects
+ * @param $opts_array Request options
+ * @return A tree of SimpleXML objects
+ */
+function submit_request($req, $skipVerify, $opts_array){
+ $xcathost = "localhost";
+ $port = "3001";
+ $rsp = FALSE;
+ $response = '';
+ $cleanexit = 0;
+
+ // Determine whether to flush output or not
+ $flush = false;
+ if ($opts_array && in_array("flush", $opts_array)) {
+ $flush = true;
+ }
+
+ // Determine how to handle the flush output
+ // You can specify a function name, in place of TBD, to handle the flush output
+ $flush_format = "";
+ if ($opts_array && in_array("flush-format=TBD", $opts_array)) {
+ $flush_format = "TBD";
+ }
+
+ // Open syslog, include the process ID and also send
+ // the log to standard error, and use a user defined
+ // logging mechanism
+ openlog("xCAT-UI", LOG_PID | LOG_PERROR, LOG_LOCAL0);
+
+ // Open a socket to xcatd
+ syslog(LOG_INFO, "Opening socket to xcatd...");
+ if($fp = stream_socket_client('ssl://'.$xcathost.':'.$port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT)){
+ $reqXML = $req->asXML();
+ $nr = $req->noderange;
+ $cmd = $req->command;
+
+ syslog(LOG_INFO, "Sending request: $cmd $nr");
+ stream_set_blocking($fp, 0); // Set as non-blocking
+ fwrite($fp,$req->asXML()); // Send XML to xcatd
+ set_time_limit(900); // Set 15 minutes timeout (for long running requests)
+ // The default is 30 seconds which is too short for some requests
+
+ // Turn on output buffering
+ ob_start();
+ while(!feof($fp)) { // Read until there is no more
+ // Remove newlines and add it to the response
+ $str = fread($fp, 8192);
+ if ($str) {
+ $response .= preg_replace('/>\n\s*', '><', $str);
+
+ // Flush output to browser
+ if ($flush) {
+ // Strip HTML tags from output
+ if ($tmp = trim(strip_tags($str))) {
+ // Format the output based on what was given for $flush_format
+ if ($flush_format == "TDB") {
+ format_TBD($tmp);
+ } else {
+ // Print out output by default
+ echo '' . $tmp . ' ';
+ ob_flush();
+ flush();
+ }
+ }
+ }
+ }
+
+ // Look for serverdone response
+ $fullpattern = '/\s*\s*<\/serverdone>\s*<\/xcatresponse>/';
+ $mixedpattern = '/\s*<\/serverdone>.*<\/xcatresponse>/';
+ $recentpattern = '/<\/xcatresponse>/';
+ if(preg_match($recentpattern,$str) && preg_match($mixedpattern,$response)) {
+ // Transaction is done,
+ // Package up XML and return it
+ // Remove the serverdone response and put an xcat tag around the rest
+ $count = 0;
+ $response = preg_replace($fullpattern,'', $response, -1, $count); // 1st try to remove the long pattern
+ if (!$count) { $response = preg_replace($mixedpattern,'', $response) . ' /'; } // if its not there, then remove the short pattern
+ $response = "$response ";
+ //delete the \n between '>' and '<'
+ $response = preg_replace('/>\n\s*', '><', $response);
+ //replace the '\n' by ':|:' in the data area.
+ $response = preg_replace('/\n/', ':|:', $response);
+ $rsp = simplexml_load_string($response,'SimpleXMLElement', LIBXML_NOCDATA);
+ $cleanexit = 1;
+ break;
+ }
+ } // End of while(!feof($fp))
+
+ syslog(LOG_INFO, "($cmd $nr) Sending response");
+ fclose($fp);
+ } else {
+ echo "xCAT submit request socket error: $errno - $errstr
";
+ }
+
+ // Flush (send) the output buffer and turn off output buffering
+ ob_end_flush();
+
+ // Close syslog
+ closelog();
+
+ if(! $cleanexit) {
+ if (preg_match('/^\s*.*<\/xcatresponse>\s*$/',$response)) {
+ // Probably an error message
+ $response = "$response ";
+ $rsp = simplexml_load_string($response,'SimpleXMLElement', LIBXML_NOCDATA);
+ }
+ elseif(!$skipVerify) {
+ echo "(Error) xCAT response ended prematurely: ", htmlentities($response), "
";
+ $rsp = FALSE;
+ }
+ }
+ return $rsp;
+}
+
+/**
+ * Enable password storage to split between cookie and session variable
+ *
+ * @param $data
+ * @param $key
+ * @return
+ */
+function xorcrypt($data, $key) {
+ $datalen = strlen($data);
+ $keylen = strlen($key);
+ for ($i=0;$i<$datalen;$i++) {
+ $data[$i] = chr(ord($data[$i])^ord($key[$i]));
+ }
+
+ return $data;
+}
+
+/**
+ * Get RAND characters
+ *
+ * @param $length Length of characters
+ * @return RAND characters
+ */
+function getrandchars($length) {
+ $charset = '0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*';
+ $charsize = strlen($charset);
+ srand();
+ $chars = '';
+ for ($i=0;$i<$length;$i++) {
+ $num=rand()%$charsize;
+ $chars=$chars.substr($charset,$num,1);
+ }
+
+ return $chars;
+}
+
+/**
+ * Format a given string and echo it back to the browser
+ *
+ * @param $str String
+ * @return Nothing
+ */
+function format_TBD($str) {
+ // Format a given string however you want it
+ echo $tmp . ' ';
+ flush();
+}
+
+/**
+ * Get password
+ *
+ * @param Nothing
+ * @return
+ */
+function getpassword() {
+ if (isset($GLOBALS['xcatauthsecret'])) {
+ $cryptext = $GLOBALS['xcatauthsecret'];
+ } else if (isset($_COOKIE["xcatauthsecret"])) {
+ $cryptext = $_COOKIE["xcatauthsecret"];
+ } else {
+ return false;
+ }
+
+ return xorcrypt($_SESSION["secretkey"], base64_decode($cryptext));
+}
+
+/**
+ * Get the password splitting knowledge between server
+ * and client side persistant storage. Caller should regenerate
+ * session ID when contemplating a new user/password, to preclude
+ * session fixation, though fixation is limited without the secret.
+ *
+ * @param $password Password
+ * @return Nothing
+ */
+function setpassword($password) {
+ $randlen = strlen($password);
+ $key = getrandchars($randlen);
+ $cryptext = xorcrypt($password,$key);
+
+ // Non-ascii characters, encode it in base64
+ $cryptext = base64_encode($cryptext);
+ setcookie("xcatauthsecret",$cryptext,0,'/');
+ $GLOBALS["xcatauthsecret"] = $cryptext;
+ $_SESSION["secretkey"] = $key;
+}
+
+/**
+ * Determine if a user/password session exists
+ *
+ * @param Nothing
+ * @return True If user has a session.
+ * False Otherwise
+ */
+function is_logged() {
+ if (isset($_SESSION["srv_username"]) and !is_bool(getpassword())) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Determine if a user is currently logged in successfully
+ *
+ * @param Nothing
+ * @return True If the user is currently logged in successfully
+ * False Otherwise
+ */
+function isAuthenticated() {
+ if (is_logged()) {
+ if ($_SESSION["srv_xcatpassvalid"] != 1) {
+ $testcred = docmd("authcheck", "", NULL, NULL);
+ if (isset($testcred->{'xcatresponse'}->{'data'})) {
+ $result = "".$testcred->{'xcatresponse'}->{'data'};
+ if (is_numeric(strpos("Authenticated",$result))) {
+ // Logged in successfully
+ $_SESSION["srv_xcatpassvalid"] = 1;
+ } else {
+ // Not logged in
+ $_SESSION["srv_xcatpassvalid"] = 0;
+ }
+ }
+ }
+ }
+
+ if (isset($_SESSION["srv_xcatpassvalid"]) and $_SESSION["srv_xcatpassvalid"]==1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Log out of the current user session
+ *
+ * @param Nothing
+ * @return Nothing
+ */
+function logout() {
+ // Clear the secret cookie from browser
+ if (isset($_COOKIE["xcatauthsecret"])) {
+ setcookie("xcatauthsecret",'',time()-86400*7,'/');
+ }
+
+ // Expire session cookie
+ if (isset($_COOKIE[session_name()])) {
+ setcookie(session_name(),"",time()-86400*7,"/");
+ }
+
+ // Clear server store of data
+ $_SESSION=array();
+ session_destroy();
+}
+?>
diff --git a/xCAT-UI/lib/srv_log.php b/xCAT-UI/lib/srv_log.php
new file mode 100644
index 000000000..33a376cdc
--- /dev/null
+++ b/xCAT-UI/lib/srv_log.php
@@ -0,0 +1,39 @@
+
+
diff --git a/xCAT-UI/lib/srv_logout.php b/xCAT-UI/lib/srv_logout.php
new file mode 100644
index 000000000..beb493c3e
--- /dev/null
+++ b/xCAT-UI/lib/srv_logout.php
@@ -0,0 +1,10 @@
+
diff --git a/xCAT-UI/lib/ui.php b/xCAT-UI/lib/ui.php
index 422162cef..452c31b50 100644
--- a/xCAT-UI/lib/ui.php
+++ b/xCAT-UI/lib/ui.php
@@ -5,21 +5,21 @@
* @param Nothing
* @return Nothing
*/
-function loadPage(){
+function loadPage() {
// Include CSS and Javascripts
echo
'
xCAT Console
-
+
-
-
+
+
';
diff --git a/xCAT-UI/service.php b/xCAT-UI/service.php
new file mode 100644
index 000000000..7c4e5e8d1
--- /dev/null
+++ b/xCAT-UI/service.php
@@ -0,0 +1,87 @@
+
+
+ xCAT Service Portal
+
+
+
+
+
+
+
+
+
+
+ ';
+
+// Create header menu
+echo
+'
+ ';
+
+// Create content area
+echo '
';
+
+// End of page
+echo
+ '
+';
+
+// Login user
+if (!isAuthenticated()) {
+ // xcatauth.js will open a dialog box asking for the user name and password
+ echo
+ '
+
+
+
+
Open Source. EPL License.
+
';
+} else {
+ // Initialize page
+ echo
+ '';
+}
+?>