diff --git a/xCAT-UI/css/style.css b/xCAT-UI/css/style.css index b3a56eed6..9fc78eb5c 100644 --- a/xCAT-UI/css/style.css +++ b/xCAT-UI/css/style.css @@ -114,6 +114,10 @@ body { color: inherit; } +pre { + font-size: 10px; +} + /*--------------- Groups ---------------*/ #groups { width: 150px; diff --git a/xCAT-UI/js/custom/blade.js b/xCAT-UI/js/custom/blade.js index 3ac788dc4..23e0c34bb 100644 --- a/xCAT-UI/js/custom/blade.js +++ b/xCAT-UI/js/custom/blade.js @@ -14,6 +14,17 @@ var bladePlugin = function() { }; +/** + * Clone node (service page) + * + * @param node + * Node to clone + * @return Nothing + */ +bladePlugin.prototype.serviceClone = function(node) { + +}; + /** * Load provision page (service page) * diff --git a/xCAT-UI/js/custom/hmc.js b/xCAT-UI/js/custom/hmc.js index bf83d1306..ba0ce1e61 100644 --- a/xCAT-UI/js/custom/hmc.js +++ b/xCAT-UI/js/custom/hmc.js @@ -14,6 +14,17 @@ var hmcPlugin = function() { }; +/** + * Clone node (service page) + * + * @param node + * Node to clone + * @return Nothing + */ +hmcPlugin.prototype.serviceClone = function(node) { + +}; + /** * Load provision page (service page) * diff --git a/xCAT-UI/js/custom/ipmi.js b/xCAT-UI/js/custom/ipmi.js index 2b2e132b6..3c74067f3 100644 --- a/xCAT-UI/js/custom/ipmi.js +++ b/xCAT-UI/js/custom/ipmi.js @@ -14,6 +14,17 @@ var ipmiPlugin = function() { }; +/** + * Clone node (service page) + * + * @param node + * Node to clone + * @return Nothing + */ +ipmiPlugin.prototype.serviceClone = function(node) { + +}; + /** * Load provision page (service page) * diff --git a/xCAT-UI/js/custom/zvm.js b/xCAT-UI/js/custom/zvm.js index 72ea8b179..a143f5eeb 100644 --- a/xCAT-UI/js/custom/zvm.js +++ b/xCAT-UI/js/custom/zvm.js @@ -15,6 +15,44 @@ var zvmPlugin = function() { }; +/** + * Clone node (service page) + * + * @param node + * Node to clone + * @return Nothing + */ +zvmPlugin.prototype.serviceClone = function(node) { + var statBar = createStatusBar(node + 'CloneStat'); + var loader = createLoader(''); + statBar.find('div').append(loader); + statBar.prependTo($('#manageTab')); + + var owner = $.cookie('srv_usrname'); + var group = getUserNodeAttr(node, 'groups'); + + // Submit request to clone VM + // webportal clonezlinux [src node] [group] [owner] + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'webportal', + tgt : '', + args : 'clonezlinux;' + node + ';' + group + ';' + owner, + msg : '' + }, + success:function(data) { + // Remove loader + statBar.find('img').remove(); + // Append output to status bar + for (var i in data.rsp) { + statBar.find('div').append($('
').append(data.rsp[i]));
+        	}
+        }
+    });
+};
+
 /**
  * Load provision page (service page)
  * 
@@ -68,7 +106,7 @@ zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) {
 		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');;
+		var owner = $.cookie('srv_usrname');
 		
 		// Begin by creating VM
 		createzVM(tabId, group, hcp, img, owner);
@@ -79,7 +117,7 @@ zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) {
 	loadSrvGroups(groupCol);
 	loadOSImages(imageCol);
 	
-	 // Get zVM host names
+	// Get zVM host names
 	if (!$.cookie('srv_zvm')){
 		$.ajax( {
 			url : 'lib/srv_cmd.php',
diff --git a/xCAT-UI/js/service/service.js b/xCAT-UI/js/service/service.js
index ad639acbd..f85d043f0 100644
--- a/xCAT-UI/js/service/service.js
+++ b/xCAT-UI/js/service/service.js
@@ -517,6 +517,15 @@ function loadNodesTable(data) {
 		}
 	});
 	
+	// Clone
+	var cloneLnk = $('Clone');
+	cloneLnk.click(function() {
+		var tgtNodes = getNodesChecked(nodesDTId);
+		if (tgtNodes) {
+			cloneNode(tgtNodes);
+		}
+	});
+	
 	// Delete
 	var deleteLnk = $('Delete');
 	deleteLnk.click(function() {
@@ -540,7 +549,7 @@ function loadNodesTable(data) {
 	
 	// Prepend menu to datatable
 	var actionsLnk = 'Actions';
-	var actionMenu = createMenu([deleteLnk, powerOnLnk, powerOffLnk, monitorOnLnk, monitorOffLnk, unlockLnk]);
+	var actionMenu = createMenu([cloneLnk, deleteLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, unlockLnk]);
 	var menu = createMenu([[actionsLnk, actionMenu]]);
 	menu.superfish();
 	actionBar.append(menu);
@@ -1171,6 +1180,43 @@ function monitorNode(node, monitor) {
 	}
 }
 
+/**
+ * Open a dialog to clone node
+ * 
+ * @param tgtNodes
+ *            Nodes to clone
+ * @return Nothing
+ */
+function cloneNode(tgtNodes) {	
+	var nodes = tgtNodes.split(',');
+	
+	for (var n in nodes) {
+		// Get hardware that was selected
+		var hw = getUserNodeAttr(nodes[n], 'mgt');
+		
+		// Create an instance of the plugin
+        var plugin;
+        switch (hw) {
+        case "blade":
+            plugin = new bladePlugin();
+            break;
+        case "hmc":
+            plugin = new hmcPlugin();
+            break;
+        case "ipmi":
+            plugin = new ipmiPlugin();
+            break;
+        case "zvm":
+            plugin = new zvmPlugin();	        	
+            break;
+        }
+
+        // Clone node
+        plugin.serviceClone(nodes[n]);				
+	}
+}
+	
+
 /**
  * Open a dialog to delete node
  * 
diff --git a/xCAT-UI/js/service/utils.js b/xCAT-UI/js/service/utils.js
index 557e795c4..62ed47c24 100644
--- a/xCAT-UI/js/service/utils.js
+++ b/xCAT-UI/js/service/utils.js
@@ -318,4 +318,43 @@ function showChdefOutput(data) {
 	}
 	
 	info.append(prg);
+}
+
+/**
+ * Get an attribute of a given node
+ * 
+ * @param node
+ *            The node
+ * @param attrName
+ *            The attribute
+ * @return The attribute of the node
+ */
+function getUserNodeAttr(node, attrName) {
+	// Get the row
+	var row = $('[id=' + node + ']').parents('tr');
+
+	// Search for the column containing the attribute
+	var attrCol;
+	
+	var cols = row.parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th');
+	// Loop through each column
+	for (var i in cols) {
+		// Find column that matches the attribute
+		if (cols.eq(i).html() == attrName) {
+			attrCol = cols.eq(i);
+			break;
+		}
+	}
+	
+	// If the column containing the attribute is found
+	if (attrCol) {
+		// Get the attribute column index
+		var attrIndex = attrCol.index();
+
+		// Get the attribute for the given node
+		var attr = row.find('td:eq(' + attrIndex + ')');
+		return attr.text();
+	} else {
+		return '';
+	}
 }
\ No newline at end of file
diff --git a/xCAT-UI/lib/functions.php b/xCAT-UI/lib/functions.php
index b4cceb1ba..3fa8eded5 100644
--- a/xCAT-UI/lib/functions.php
+++ b/xCAT-UI/lib/functions.php
@@ -111,7 +111,7 @@ function submit_request($req, $skipVerify, $opts_array){
 							format_TBD($tmp);
 						} else {
 							// Print out output by default
-							echo '
' . $tmp . '
'; + echo '
' . $tmp . '
'; ob_flush(); flush(); } diff --git a/xCAT-UI/lib/srv_functions.php b/xCAT-UI/lib/srv_functions.php index e2eb01a3a..3f427cab3 100644 --- a/xCAT-UI/lib/srv_functions.php +++ b/xCAT-UI/lib/srv_functions.php @@ -111,7 +111,7 @@ function submit_request($req, $skipVerify, $opts_array){ format_TBD($tmp); } else { // Print out output by default - echo '
' . $tmp . '
'; + echo '
' . $tmp . '
'; ob_flush(); flush(); } diff --git a/xCAT-UI/xcat/plugins/webportal.pm b/xCAT-UI/xcat/plugins/webportal.pm index e87aa2d3a..6a2d0fbe7 100644 --- a/xCAT-UI/xcat/plugins/webportal.pm +++ b/xCAT-UI/xcat/plugins/webportal.pm @@ -34,8 +34,9 @@ sub process_request { my $callback = shift; my $sub_req = shift; my %authorized_cmds = ( - 'lszvm' => \&lszvm, - 'provzlinux' => \&provzlinux + 'lszvm' => \&lszvm, + 'provzlinux' => \&provzlinux, + 'clonezlinux' => \&clonezlinux ); # Check if the request is authorized @@ -370,4 +371,126 @@ sub gennodename { return ($hostname, $base_digit); } -1; + +sub clonezlinux { + my ( $request, $callback, $sub_req ) = @_; + + # webportal clonezlinux [src node] [group] [owner] + my $src_node = $request->{arg}->[1]; + my $group = $request->{arg}->[2]; + my $owner = $request->{arg}->[3]; + + # Get source node's HCP + my $props = xCAT::zvmUtils->getNodeProps( 'zvm', $src_node, ('hcp') ); + my $hcp = $props->{'hcp'}; + + # Read in default disk pool and disk size /opt/zhcp/conf/default.conf on zHCP + # pool = POOL3 + # eckd_size = 10016 + my $disk_pool; + my $eckd_size; + my $fba_size; + my $default_conf = '/opt/zhcp/conf/default.conf'; + my $default_direct = '/opt/zhcp/conf/default.direct'; + + # Exit if default.conf does not exist + if ( !(`ssh $hcp "test -e $default_conf && echo Exists"`) ) { + println( $callback, '(Error) $default_conf does not exists' ); + return; + } + + # Exit if default.direct does not exist + if ( !(`ssh $hcp "test -e $default_direct && echo Exists"`) ) { + println( $callback, '(Error) $default_direct does not exists' ); + return; + } + + my $out = `ssh $hcp "cat $default_conf"`; + my @tmp = split( /\n/, $out ); + foreach (@tmp) { + # Get disk pool + if ( $_ =~ m/pool =/i ) { + $disk_pool = $_; + $disk_pool =~ s/pool =//g; + } + + # Get disk size + elsif ( $_ =~ m/eckd_size =/i ) { + $eckd_size = $_; + $eckd_size =~ s/eckd_size =//g; + } + elsif ( $_ =~ m/fba_size = /i ) { + $fba_size = $_; + $fba_size =~ s/fba_size = //g; + } + } + + println( $callback, "Your virtual machine is ready. It may take a few minutes before you can logon." ); + println( $callback, "Done!" ); + + return; + + + + +# # Create VM +# # e.g. webportal provzlinux [group] [hcp] [image] +# my ($node, $base_digit) = gennodename( $callback, $group ); +# my $userid = 'XCAT' . $base_digit; +# +# # Set node definitions +# $out = `mkdef -t node -o $node userid=$userid hcp=$hcp mgt=zvm groups=$group`; +# println( $callback, "$out" ); +# +# # Set nodetype definitions +# $out = `chtab node=$node noderes.netboot=zvm nodetype.nodetype=osi nodetype.provmethod=install nodetype.os=$os nodetype.arch=$arch nodetype.profile=$profile nodetype.comments="owner:$owner"`; +# +# # Update hosts table and DNS +# `makehosts`; +# `makedns`; +# +# # Create user directory entry replacing LXUSR with user ID +# # Use /opt/zhcp/conf/default.direct on zHCP as the template +# # USER LXUSR PSWD 512M 1G G +# # INCLUDE LNXDFLT +# # COMMAND SET VSWITCH VSW2 GRANT LXUSR +# $out = `ssh $hcp "sed $default_direct -e s/LXUSR/$userid/g" > /tmp/$node-direct.txt`; +# $out = `mkvm $node /tmp/$node-direct.txt`; +# `rm -rf /tmp/$node-direct.txt`; +# println( $callback, "$out" ); +# if ( $out =~ m/Error/i ) { +# return; +# } +# +# # Update DHCP +# `makedhcp -a`; +# +# # Toggle node power so COMMAND SET will get executed +# `rpower $node on`; +# `rpower $node off`; +# +# # Punch kernel, initrd, and ramdisk to node reader +# $out = `nodeset $node install`; +# println( $callback, "$out" ); +# if ( $out =~ m/Error/i ) { +# return; +# } +# +# # IPL reader and begin installation +# $out = `rnetboot $node ipl=00C`; +# println( $callback, "$out" ); +# if ( $out =~ m/Error/i ) { +# return; +# } +# +# # Configure Ganglia monitoring +# $out = `moncfg gangliamon $node -r`; +# +# # Show node information, e.g. IP, hostname, and root password +# $out = `lsdef $node | egrep "ip=|hostnames="`; +# my $rootpw = getsysrootpw(); +# println( $callback, "Your virtual machine is ready. It may take a few minutes before you can logon using VNC ($node:1). Below is your VM attributes." ); +# println( $callback, "$out" ); +# println( $callback, " rootpw = $rootpw" ); +} +1; \ No newline at end of file