diff --git a/perl-xCAT/xCAT/zvmCPUtils.pm b/perl-xCAT/xCAT/zvmCPUtils.pm index 3b3b75e4f..f66ba7513 100644 --- a/perl-xCAT/xCAT/zvmCPUtils.pm +++ b/perl-xCAT/xCAT/zvmCPUtils.pm @@ -279,6 +279,7 @@ sub getNetworkNames { # Get network names my $out; + my $outmsg; my $names; my $count; my @parms; @@ -369,11 +370,12 @@ sub getNetworkNames { # use vmcp q lan if this is not the zhcp node } else { #$out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /sbin/vmcp q lan | egrep 'LAN|VSWITCH'"`; - my $cmd = $sudo . ' /sbin/vmcp q lan | egrep "LAN|VSWITCH"'; + my $cmd = $sudo . ' /sbin/vmcp q lan'; $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput($out) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i 'LAN|VSWITCH'`; @lines = split( '\n', $out ); foreach (@lines) { @@ -431,11 +433,12 @@ sub getNetworkNamesArray { # Get the networks used by the node #my $out = `ssh $user\@$node "$sudo /sbin/vmcp q v nic" | egrep -i "VSWITCH|LAN"`; - my $cmd = $sudo . ' /sbin/vmcp q v nic | egrep -i "VSWITCH|LAN"'; + my $cmd = $sudo . ' /sbin/vmcp q v nic'; my $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput($out) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i 'VSWITCH|LAN'`; my @lines = split( '\n', $out ); # Loop through each line @@ -549,7 +552,7 @@ sub getNetwork { xCAT::zvmUtils->printSyslog("ssh $user\@$hcp $sudo $dir/smcli Virtual_Network_LAN_Query -T $hcpUserId -n $netNameQuery -o '*'"); $out = `ssh $user\@$hcp "$sudo $dir/smcli Virtual_Network_LAN_Query -T $hcpUserId -n $netNameQuery -o '*' "`; $rc = $? >> 8; - if ($rc) { + if ($rc == 255) { $retStr = "(Error) unable to communicate with the zhcp system: $hcpUserId"; xCAT::zvmUtils->printSyslog($retStr); return $retStr; @@ -674,11 +677,12 @@ sub getVswitchId { # Get VSwitch #my $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /sbin/vmcp q v nic" | grep "VSWITCH"`; - my $cmd = $sudo . ' /sbin/vmcp q v nic | grep "VSWITCH"'; + my $cmd = $sudo . ' /sbin/vmcp q v nic'; my $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput($out) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i 'VSWITCH'`; my @lines = split( '\n', $out ); my @parms; my @vswitch; @@ -731,8 +735,9 @@ sub grantVSwitch { # Use SMAPI EXEC, use new extended SMAPI vs old one # my $out = `ssh $user\@$hcp "$sudo $dir/smcli Virtual_Network_Vswitch_Set -T SYSTEM -n $vswitchId -I $userId -u 2"`; # xCAT::zvmUtils->printSyslog("grantVSwitch- ssh $user\@$hcp $sudo $dir/smcli Virtual_Network_Vswitch_Set -T SYSTEM -n $vswitchId -I $userId -u 2"); + xCAT::zvmUtils->printSyslog( "grantVSwitch- ssh $user\@$hcp $sudo $dir/smcli Virtual_Network_Vswitch_Set_Extended -T SYSTEM -k 'switch_name='$vswitchId -k 'grant_userid='$userId -k 'persist=YES '$lanidparm" ); my $out = `ssh $user\@$hcp "$sudo $dir/smcli Virtual_Network_Vswitch_Set_Extended -T SYSTEM -k 'switch_name='$vswitchId -k 'grant_userid='$userId -k 'persist=YES' $lanidparm"`; - xCAT::zvmUtils->printSyslog("grantVSwitch- ssh $user\@$hcp $sudo $dir/smcli Virtual_Network_Vswitch_Set_Extended -T SYSTEM -k 'switch_name='$vswitchId -k 'grant_userid='$userId -k 'persist=YES '$lanidparm"); + $out = xCAT::zvmUtils->trimStr($out); # If return string contains 'Done' - Operation was successful @@ -915,8 +920,9 @@ sub smapiFlashCopy { SPOOL file class to be assigned to the punched file "" means that the current class is to be used anything else is the class to set on the punched file - Returns : Operation results (Done/Failed) - Example : my $rc = xCAT::zvmCPUtils->punch2Reader($hcp, $userId, $srcFile, $tgtFile, $options, $spoolClass ); + Returns : Operation results ("Done" or "Failed" with additional info) + Example : my $response = xCAT::zvmCPUtils->punch2Reader( $user, $hcp, $userId, $srcFile, + $tgtFile, $options, $spoolClass ); =cut @@ -950,29 +956,32 @@ sub punch2Reader { $vmur = "/usr/sbin/vmur"; } - my $done = 0; - # Punch the file. A loop is done in case the punch is currently in use. - until ( $done ) { + my $done = 0; + my $maxTries = 12; # 12 attempts with 15 second waits for punch to become available + my $maxTime = $maxTries / 4; # Total time: 3 minutes + for ( my $i=0; ( $i < $maxTries and !$done ); $i++ ) { $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo $vmur punch $options $punchTarget -r $srcFile -N $tgtFile" 2>&1`; $rc = $? >> 8; if ( $rc == 255 ) { + xCAT::zvmUtils->printSyslog( "(Error) In punch2Reader(), SSH communication with $hcp failed for command: $vmur punch" ); $subResp = "Failed to communicate with the zHCP system: $hcp"; $done = 1; } elsif ( $out =~ m/A concurrent instance of vmur is already active/i ) { # Recoverable error: retry the command after a delay xCAT::zvmUtils->printSyslog( "punch2Reader() Punch in use on $hcp, retrying in 15 seconds" ); + $subResp = "Failed, Punch in use on $hcp for over $maxTime minutes."; # Assume it will never become available sleep( 15 ); + } elsif ( $rc == 0 ) { + # Punch appears successful + $subResp = ''; + $punched = 1; + $done = 1; } else { - # Punch appears successful -- Look for the completion string - my $searchStr = "created"; - if ( $out =~ m/$searchStr/i ) { - $punched = 1; - } else { - chomp( $out ); - $subResp = "Failed, punch info: '$out'"; - xCAT::zvmUtils->printSyslog( "punch2Reader() Failed punching $srcFile to $userId from $hcp, rc: $rc, out: '$out'" ); - } + # Punch failed for other than currently in use. + chomp( $out ); + $subResp = "Failed, punch info: '$out'"; + xCAT::zvmUtils->printSyslog( "punch2Reader() Failed punching $srcFile to $userId from $hcp, rc: $rc, out: '$out'" ); $done = 1; } } @@ -996,6 +1005,7 @@ sub punch2Reader { $rc = $? >> 8; if ( $rc == 255 ) { # SSH failure to communicate with zHCP. Nothing to do, file remains in zHCP's reader. + xCAT::zvmUtils->printSyslog( "(Error) In punch2Reader(), SSH communication with $hcp failed for command: vmcp change rdr $spoolId class $spoolClass" ); $subResp = "Failed to communicate with the zHCP system to change the reader file $spoolId to class $spoolClass: $hcp"; } elsif ( $rc != 0 ) { # Generic failure of transfer command. @@ -1013,6 +1023,7 @@ sub punch2Reader { $subResp = "Done"; } elsif ( $rc == 255 ) { # SSH failure to communicate with zHCP. Nothing to do, file remains in zHCP's reader. + xCAT::zvmUtils->printSyslog( "(Error) In punch2Reader(), SSH communication with $hcp failed for command: vmcp transfer rdr $spoolId to $userId" ); $subResp = "Failed to communicate with the zHCP system to transfer reader file $spoolId: $hcp"; } else { # Generic failure of transfer command. @@ -1028,6 +1039,7 @@ sub punch2Reader { $rc = $? >> 8; if ( $rc == 255 ) { # SSH failure to communicate with zHCP. Nothing to do, file remains in zHCP's reader. + xCAT::zvmUtils->printSyslog( "(Error) In punch2Reader(), SSH communication with $hcp failed for command: vmcp purge reader $spoolId" ); $subResp = $subResp. "\nFailed to communicate with the zHCP system to purge reader file $spoolId: $hcp"; } elsif ( $rc != 0 ) { # Any failure is bad and unrecoverable. @@ -1194,7 +1206,7 @@ sub getNetworkLayer { Arguments : User (root or non-root) zHCP Name of network - Returns : Network type (VSWITCH/HIPERS/QDIO) + Returns : Network type (VSWITCH/HIPERS/QDIO) or string containing (Error)... Example : my $netType = xCAT::zvmCPUtils->getNetworkType($hcp, $netName); =cut @@ -1209,7 +1221,15 @@ sub getNetworkType { } # Get network details - my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q lan $netName" | grep "Type"`; + my $outmsg; + my $rc; + my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q lan $netName"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $user\@$hcp \"$sudo /sbin/vmcp q lan $netName\"", $hcp, "getNetworkType", $out ); + if ($rc != 0) { + return $outmsg; + } + + $out = `echo "$out" | egrep -a 'Type'`; # Go through each line and determine network type my @lines = split( '\n', $out ); diff --git a/perl-xCAT/xCAT/zvmUtils.pm b/perl-xCAT/xCAT/zvmUtils.pm index 30ef238ce..e191be899 100644 --- a/perl-xCAT/xCAT/zvmUtils.pm +++ b/perl-xCAT/xCAT/zvmUtils.pm @@ -374,7 +374,7 @@ sub isZvmNode { # Look in 'zvm' table my $tab = xCAT::Table->new( 'zvm', -create => 1, -autocommit => 0 ); - my @results = $tab->getAllAttribsWhere( "node like '%" . $node . "%'", 'userid' ); + my @results = $tab->getAllAttribsWhere( "node = '" . $node . "'", 'userid' ); foreach (@results) { # Return 'TRUE' if given node is in the table @@ -563,17 +563,19 @@ sub getIfcfgByNic { # Go through each line foreach (@parms) { + my $filename = $_; # If the network file contains the NIC address #$out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo cat $_" | egrep -i "$nic"`; - my $cmd = $sudo . ' cat $_ | egrep -i "' . $nic .'"'; + my $cmd = $sudo . ' cat $filename'; $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i "$nic"`; if ($out) { # Return network file path - return ($_); + return ($filename); } } } @@ -581,11 +583,12 @@ sub getIfcfgByNic { # If it is SLES 10 - ifcfg-qeth file is in /etc/sysconfig/network elsif ( $os =~ m/SUSE Linux Enterprise Server 10/i ) { #$out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo ls /etc/sysconfig/network/ifcfg-qeth*" | grep -i "$nic"`; - my $cmd = $sudo . ' ls /etc/sysconfig/network/ifcfg-qeth* | grep -i "' . $nic .'"'; + my $cmd = $sudo . ' ls /etc/sysconfig/network/ifcfg-qeth*'; $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i "$nic"`; @parms = split( '\n', $out ); return ( $parms[0] ); } @@ -607,11 +610,12 @@ sub getIfcfgByNic { # If the network file contains the NIC address #$out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo cat $_" | grep -i "$nic"`; - my $cmd = $sudo . ' cat $_ | grep -i "' . $nic .'"'; + my $cmd = $sudo . ' cat $_'; $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i "$nic"`; if ($out) { # Return ifcfg-eth file path @@ -691,11 +695,12 @@ sub getRootDeviceAddr { # Get the root device node # LVM is not supported #my $out = `ssh $user\@$node "mount" | grep "/ type" | sed 's/1//'`; - my $cmd = $sudo . ' mount | grep "/ type" | sed \'s/1//\''; + my $cmd = $sudo . ' mount'; my $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i "/ type" | sed \'s/1//\'`; my @parms = split( " ", $out ); @parms = split( "/", xCAT::zvmUtils->trimStr( $parms[0] ) ); @@ -703,11 +708,12 @@ sub getRootDeviceAddr { # Get disk address #$out = `ssh $user\@$node "cat /proc/dasd/devices" | grep "$devNode" | sed 's/(ECKD)//' | sed 's/(FBA )//' | sed 's/0.0.//'`; - $cmd = $sudo . ' cat /proc/dasd/devices | grep "' . $devNode . '" | sed "s/(ECKD)//" | sed "s/(FBA )//" | sed \'s/0.0.//\''; + $cmd = $sudo . ' cat /proc/dasd/devices'; $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i "$devNode" | sed "s/(ECKD)//" | sed "s/(FBA )//" | sed \'s/0.0.//\'`; @parms = split( " ", $out ); return ( $parms[0] ); @@ -766,7 +772,7 @@ sub disableEnableDisk { Description : Get the MDISK statements in the user entry of a given node Arguments : User (root or non-root) Node - Returns : MDISK statements + Returns : MDISK statements array or or string containing (Error)... Example : my @mdisks = xCAT::zvmUtils->getMdisks($callback, $user, $node); =cut @@ -793,7 +799,14 @@ sub getMdisks { # Get node userID my $userId = $propVals->{'userid'}; - my $out = `ssh $user\@$hcp "$sudo $dir/getuserentry $userId" | grep "MDISK"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo $dir/getuserentry $userId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo $dir/getuserentry $userId\"", $hcp, "getMdisks", $out, $node ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "MDISK"`; # Get MDISK statements my @lines = split( '\n', $out ); @@ -819,7 +832,7 @@ sub getMdisks { Description : Get the DEDICATE statements in the user entry of a given node Arguments : User (root or non-root) Node - Returns : DEDICATE statements + Returns : DEDICATE statements array or string containing (Error)... Example : my @dedicates = xCAT::zvmUtils->getDedicates($callback, $user, $node); =cut @@ -846,7 +859,14 @@ sub getDedicates { # Get node userId my $userId = $propVals->{'userid'}; - my $out = `ssh $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId" | egrep -i "DEDICATE"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "commandString", $hcp, "getMdisks", $out, $node ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "DEDICATE"`; # Get DEDICATE statements my @lines = split( '\n', $out ); @@ -868,7 +888,7 @@ sub getDedicates { Description : Get the COMMAND statements in the user entry of a given node Arguments : User (root or non-root) Node - Returns : COMMAND statements + Returns : COMMAND statements array or or string containing (Error)... Example : my @commands = xCAT::zvmUtils->getCommands($callback, $user, $node); =cut @@ -895,7 +915,14 @@ sub getCommands { # Get node userId my $userId = $propVals->{'userid'}; - my $out = `ssh $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId" | egrep -i "COMMAND"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo $dir/smcli Image_Query_DM -T $userId\"", $hcp, "getCommands", $out, $node ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "COMMAND"`; # Get COMMAND statements my @lines = split( '\n', $out ); @@ -919,7 +946,7 @@ sub getCommands { Arguments : User (root or non-root) Node File name to save user entry under - Returns : Nothing + Returns : Nothing, or string containing (Error)... Example : my $out = xCAT::zvmUtils->getUserEntryWODisk($callback, $user, $node, $file); =cut @@ -956,8 +983,15 @@ sub getUserEntryWODisk { return; } - my $out = `ssh $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId" | sed '\$d' | grep -v "MDISK"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo $dir/smcli Image_Query_DM -T $userId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo $dir/smcli Image_Query_DM -T $userId\"", $hcp, "getUserEntryWODisk", $out, $node ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | sed '\$d' | grep -a -i -v "MDISK"`; # Create a file to save output open( DIRENTRY, ">$file" ); @@ -1064,35 +1098,71 @@ sub checkOutputExtractReason { #------------------------------------------------------- -=head3 checkSSHOutput +=head3 checkSSH_Rc + + Description : Check for SSH errors, and command return code failure - Description : Check for SSH errors, and command failure Arguments : $? - command that was issued - Returns : rc = 0 Good output - rc = -1 Error occurred - $outmsg = error message string if $rc = -1 + command that was issued (do not pass in a password in cmd string, just mask it out) + node the SSH is targeting + function name the SSH call was done in + optional command output + optional final target node (used to prefix "Node: " to error message. Helps in tracing hcp calls on behalf of a node) + optional syslog supression, "NONE", "SSHONLY" defaults to syslog message of any SSH or command error + + Returns : rc = 0 Good output + rc = 255 Error occurred in SSH + rc > 0 Command error + + $outmsg = error message string if $rc !=0 + plus syslog entry for non zero errors - Example : ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "Command being issued"); + Example : ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "Command being issued", $hcp, "testfunc", $out, $node, "NONE"); =cut #------------------------------------------------------- -sub checkSSHOutput { - my ( $class, $rc, $cmd ) = @_; +sub checkSSH_Rc { + my ( $class, $rc, $cmd, $tgtNode, $functionName, $cmdOutput, $finalTargetNode, $syslogOptions ) = @_; my $msgTxt = ''; + my $logit = 2; + + if (!defined $cmdOutput) { + $cmdOutput = ''; + } else { + $cmdOutput = " Output: " . $cmdOutput . " "; + } + + if (!defined $finalTargetNode) { + $finalTargetNode = ''; + } else { + $finalTargetNode = "Node: " . $finalTargetNode . " "; + } + if (defined $syslogOptions) { + if ( $syslogOptions =~ m/NONE/i ) { + $logit = 0; + } elsif ( $syslogOptions =~ m/SSHONLY/i ) { + $logit = 1; + } + } + + $rc = $rc >> 8; if ( $rc == 255 ) { - # SSH failure to communicate with zHCP. - $msgTxt = "SSH Failed to communicate when trying command: $cmd"; - xCAT::zvmUtils->printSyslog("$msgTxt"); - return (-1, $msgTxt); + # SSH failure to communicate with $tgtNode. + $msgTxt = "$finalTargetNode" . "(Error) In $functionName(), SSH communication to $tgtNode failed for command: $cmd"; + if ($logit > 0 ) { + xCAT::zvmUtils->printSyslog("$msgTxt"); + } + return ($rc, $msgTxt); } elsif ( $rc != 0 ) { # Generic failure of the command. - $msgTxt = "Command failed with return code $rc trying to issue cmd: $cmd"; - xCAT::zvmUtils->printSyslog("$msgTxt"); + $msgTxt = "$finalTargetNode" . "(Error) In $functionName(), command to $tgtNode failed with return code $rc for: $cmd" . "$cmdOutput"; + if ($logit > 1 ) { + xCAT::zvmUtils->printSyslog("$msgTxt"); + } return ($rc, $msgTxt); } return 0; @@ -1122,11 +1192,12 @@ sub getDeviceNode { # Determine device node #my $out = `ssh $user\@$node "$sudo cat /proc/dasd/devices" | grep ".$tgtAddr("`; - my $cmd = $sudo . ' cat /proc/dasd/devices | grep ".' . $tgtAddr . '("'; + my $cmd = $sudo . ' cat /proc/dasd/devices'; my $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i ".$tgtAddr("`; my @words = split(' ', $out); my $tgtDevNode; @@ -1168,11 +1239,12 @@ sub getDeviceNodeAddr { # /proc/dasd/devices look similar to this: # 0.0.0100(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 1802880 blocks, 7042 MB #my $addr = `ssh $user\@$node "$sudo cat /proc/dasd/devices" | grep -i "is $deviceNode"`; - my $cmd = $sudo . ' cat /proc/dasd/devices | grep -i "is ' . $deviceNode . '"'; + my $cmd = $sudo . ' cat /proc/dasd/devices'; my $addr = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $addr ) == -1) { return $addr; } + $addr = `echo "$addr" | egrep -a -i "is $deviceNode"`; $addr =~ s/ +/ /g; $addr =~ s/^0.0.([0-9a-f]*).*/$1/; chomp($addr); @@ -1205,11 +1277,12 @@ sub isAddressUsed { # Search for disk address #my $out = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /sbin/vmcp q v dasd" | grep "DASD $address"`; - my $cmd = $sudo . ' /sbin/vmcp q v dasd | grep "DASD '. $address. '"'; + my $cmd = $sudo . ' /sbin/vmcp q v dasd'; my $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i "DASD $address"`; if ($out) { return 0; } @@ -1344,7 +1417,7 @@ sub generateMacId { Arguments : User (root or non-root) Node MAC suffix - Returns : MAC address + Returns : MAC address or string containing (Error)... Example : my $mac = xCAT::zvmUtils->createMacAddr($user, $node, $suffix); =cut @@ -1369,14 +1442,22 @@ sub createMacAddr { } # Get USER Prefix - my $prefix = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q vmlan" | egrep -i "USER Prefix:"`; + my $outmsg; + my $rc; + my $prefix; + my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q vmlan"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $user\@$hcp \"$sudo /sbin/vmcp q vmlan\"", $hcp, "createMacAddr", $out, $node ); + if ($rc != 0) { + return $outmsg; + } + $prefix = `echo "$out" | egrep -a -i "USER Prefix:"`; $prefix =~ s/(.*?)USER Prefix:(.*)/$2/; $prefix =~ s/^\s+//; $prefix =~ s/\s+$//; - # Get MACADDR Prefix instead if USER Prefix is not defined + # Get MACADDR Prefix instead if USER Prefix is not defined, use saved out data if (!$prefix) { - $prefix = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo /sbin/vmcp q vmlan" | egrep -i "MACADDR Prefix:"`; + $prefix = `echo "$out" | egrep -a -i "MACADDR Prefix:"`; $prefix =~ s/(.*?)MACADDR Prefix:(.*)/$2/; $prefix =~ s/^\s+//; $prefix =~ s/\s+$//; @@ -1431,11 +1512,12 @@ sub getOs { # Get operating system #my $out = `ssh -o ConnectTimeout=10 $user\@$node "$sudo cat /etc/*release" | egrep -v "LSB_VERSION"`; - my $cmd = $sudo . ' cat /etc/*release | egrep -v "LSB_VERSION"'; + my $cmd = $sudo . ' cat /etc/*release'; my $out = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return $out; } + $out = `echo "$out" | egrep -a -i -v "LSB_VERSION"`; my @results = split( '\n', $out ); return ( xCAT::zvmUtils->trimStr( $results[0] ) ); } @@ -1548,7 +1630,7 @@ sub getUserProfile { Arguments : User (root or non-root) zHCP Userid - Returns : Vswitch names + Returns : Vswitch names array or or string containing (Error)... Example : my $vSwitchNamers = xCAT::zvmCPUtils->getVswitchIdsFromDirectory($user, $hcp, $userId); =cut @@ -1572,8 +1654,15 @@ sub getVswitchIdsFromDirectory { # NICDEF=VDEV=0700 TYPE=QDIO LAN=SYSTEM SWITCHNAME=XCATVSW2 # + my $outmsg; + my $rc; xCAT::zvmUtils->printSyslog("Calling: ssh $user\@$hcp $sudo /opt/zhcp/bin/smcli Image_Definition_Query_DM -T $userId -k NICDEF | egrep -i 'SWITCHNAME'"); - my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli Image_Definition_Query_DM -T $userId -k NICDEF | egrep -i 'SWITCHNAME'"`; + my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli Image_Definition_Query_DM -T $userId -k NICDEF"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo /opt/zhcp/bin/smcli Image_Definition_Query_DM -T $userId -k NICDEF\"", $hcp, "getVswitchIdsFromDirectory", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i 'SWITCHNAME'`; # if there is nothing found, log that and return; if ( !length($out) ) { xCAT::zvmUtils->printSyslog("No SWITCHNAME found in NICDEF statement for userid $userId"); @@ -1645,11 +1734,12 @@ sub getOsVersion { # Contact the system to extract the possible files which contain pertinent data. #my $releaseInfo = `ssh -qo ConnectTimeout=2 $user\@$node "$sudo ls /dev/null $locAllEtcVerFiles 2>/dev/null | xargs grep ''"`; - my $cmd = $sudo . ' ls /dev/null '. $locAllEtcVerFiles . ' 2>/dev/null | xargs grep ""'; + my $cmd = $sudo . ' ls /dev/null '. $locAllEtcVerFiles . ' 2>/dev/null'; my $releaseInfo = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); if (xCAT::zvmUtils->checkOutput( $releaseInfo ) == -1) { return ''; } + $releaseInfo = `echo "$releaseInfo" | xargs grep ''`; $osVer = buildOsVersion( $callback, $releaseInfo, 'all' ); return $osVer; @@ -1680,9 +1770,10 @@ sub getOSFromIP { my $rc = 0; # Get operating system - my $releaseInfo = `ssh -qo ConnectTimeout=2 $ipAddr "ls /dev/null $locAllEtcVerFiles 2>/dev/null | xargs grep ''"`; + my $releaseInfo = `ssh -qo ConnectTimeout=2 $ipAddr "ls /dev/null $locAllEtcVerFiles 2>/dev/null"`; $rc = $? >> 8; if ( $rc == 0 ) { + $releaseInfo = `echo "$releaseInfo" | xargs grep ''`; $osVer = buildOsVersion( $callback, $releaseInfo, 'all' ); } else { if ( $callback ) { @@ -2034,12 +2125,13 @@ sub getZfcpInfo { chomp($tmp); # Find the size in MiB - #$size = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /usr/bin/sg_readcap $tmp" | egrep -i "Device size:"`; - my $cmd = $sudo . ' /usr/bin/sg_readcap ' . $tmp . ' | egrep -i Device size:'; + #$size = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /usr/bin/sg_readcap $tmp" | egrep -i "Device[[:space:]]size:"`; + my $cmd = $sudo . ' /usr/bin/sg_readcap ' . $tmp; $size = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $size ) == -1) { return $size; } + $size = `echo "$size" | egrep -a -i "Device[[:space:]]size:"`; $size =~ s/Device size: //g; @args = split(",", $size); $size = xCAT::zvmUtils->trimStr($args[1]); @@ -2072,7 +2164,7 @@ sub isHypervisor { # Look in 'zvm' table my $tab = xCAT::Table->new( "hypervisor", -create => 1, -autocommit => 0 ); - my @results = $tab->getAllAttribsWhere( "node like '%" . $node . "%'", 'type' ); + my @results = $tab->getAllAttribsWhere( "node = '" . $node . "'", 'type' ); foreach (@results) { # Return 'TRUE' if given node is in the table @@ -2188,12 +2280,12 @@ sub getFreeAddress { if ($type eq 'vmcp') { # When the node is up, vmcp can be used #$allUsedAddr = `ssh -o ConnectTimeout=5 $user\@$node "$sudo /sbin/vmcp q v all | awk '\$1 ~/^($deviceTypesVm)/ {print \$2}' | sort"`; - my $cmd = $sudo . '/sbin/vmcp q v all | egrep "' . $deviceTypesVm . '"'; + my $cmd = $sudo . '/sbin/vmcp q v all'; my $allUsedAddr = xCAT::zvmUtils->execcmdonVM($user, $node, $cmd); # caller sets $user to $::SUDOER if (xCAT::zvmUtils->checkOutput( $allUsedAddr ) == -1) { return -1; } - $allUsedAddr = `echo '$allUsedAddr' | awk '\$1 ~/^($deviceTypesVm)/ {print \$2}' | sort`; + $allUsedAddr = `echo '$allUsedAddr' | egrep -a -i "$deviceTypesVm"`; } else { # When the node is down, use zHCP to get its user directory entry # Get HCP @@ -2241,7 +2333,7 @@ sub getFreeAddress { Arguments : User (root or non-root) zHCP (to query on) node - Returns : In nanoseconds for used CPU time + Returns : In nanoseconds for used CPU time or string containing (Error)... Example : my $out = xCAT::zvmUtils->getUsedCpuTime($hcp, $node); =cut @@ -2261,7 +2353,14 @@ sub getUsedCpuTime { my $userId = xCAT::zvmCPUtils->getUserId($user, $node); # Call IUO function to query CPU used time - my $time = `ssh $user\@$hcp "$sudo $dir/smcli Image_Performance_Query -T $userId -c 1" | egrep -i "Used CPU time:"`; + my $outmsg; + my $rc; + my $time = `ssh $user\@$hcp "$sudo $dir/smcli Image_Performance_Query -T $userId -c 1"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo $dir/smcli Image_Performance_Query -T $userId -c 1\"", $hcp, "getUsedCpuTime", $time, $node ); + if ($rc != 0) { + return $outmsg; + } + $time = `echo "$time" | egrep -a -i "Used CPU time:"`; $time =~ s/^Used CPU time:(.*)/$1/; $time =~ s/"//g; $time =~ s/^\s+//; @@ -2401,7 +2500,7 @@ sub getSizeFromPage { Description : Get total count of logical CPUs in the LPAR Arguments : User (root or non-root) zHCP - Returns : Total CPU count + Returns : Total CPU count or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getLparCpuTotal($user, $hcp); =cut @@ -2415,7 +2514,14 @@ sub getLparCpuTotal { $sudo = ""; } - my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "LPAR CPUs Total"`; + my $outmsg; + my $rc; + my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $user\@$hcp \"$sudo cat /proc/sysinfo\"", $hcp, "getLparCpuTotal", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "LPAR CPUs Total"`; my @results = split(' ', $out); return ($results[3]); @@ -2428,7 +2534,7 @@ sub getLparCpuTotal { Description : Get count of used logical CPUs in the LPAR Arguments : User (root or non-root) zHCP - Returns : Used CPU count + Returns : Used CPU count or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getLparCpuUsed($user, $hcp); =cut @@ -2442,7 +2548,14 @@ sub getLparCpuUsed { $sudo = ""; } - my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "LPAR CPUs Configured"`; + my $outmsg; + my $rc; + my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $user\@$hcp \"$sudo cat /proc/sysinfo\"", $hcp, "getLparCpuUsed", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "LPAR CPUs Configured"`; my @results = split(' ', $out); return ($results[3]); @@ -2455,7 +2568,7 @@ sub getLparCpuUsed { Description : Get the model of this CEC (LPAR) Arguments : User (root or non-root) zHCP - Returns : Model of this CEC + Returns : Model of this CEC or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getCecModel($user, $hcp); =cut @@ -2469,7 +2582,14 @@ sub getCecModel { $sudo = ""; } - my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "^Type:"`; + my $outmsg; + my $rc; + my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $user\@$hcp \"$sudo cat /proc/sysinfo\"", $hcp, "getCecModel", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "^Type:"`; my @results = split(' ', $out); return ($results[1]); @@ -2482,7 +2602,7 @@ sub getCecModel { Description : Get the vendor of this CEC (LPAR) Arguments : User (root or non-root) zHCP - Returns : Vendor of this CEC + Returns : Vendor of this CEC or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getCecVendor($user, $hcp); =cut @@ -2496,7 +2616,14 @@ sub getCecVendor { $sudo = ""; } - my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "Manufacturer"`; + my $outmsg; + my $rc; + my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $user\@$hcp \"$sudo cat /proc/sysinfo\"", $hcp, "getCecVendor", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "Manufacturer"`; my @results = split(' ', $out); return ($results[1]); @@ -2509,7 +2636,7 @@ sub getCecVendor { Description : Get the info(name & version) for this hypervisor Arguments : User (root or non-root) zHCP - Returns : Name & version of this hypervisor + Returns : Name & version of this hypervisor or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getHypervisorInfo($user, $hcp); =cut @@ -2523,7 +2650,14 @@ sub getHypervisorInfo { $sudo = ""; } - my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo" | grep "VM00 Control Program"`; + my $outmsg; + my $rc; + my $out = `ssh -o ConnectTimeout=5 $user\@$hcp "$sudo cat /proc/sysinfo"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $user\@$hcp \"$sudo cat /proc/sysinfo\"", $hcp, "getHypervisorInfo", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "VM00 Control Program"`; my @results = split(' ', $out); my $str = "$results[3] $results[4]"; @@ -2538,7 +2672,7 @@ sub getHypervisorInfo { Description : Get the total physical memory of this LPAR Arguments : User (root or non-root) zHCP - Returns : Total physical memory + Returns : Total physical memory or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getLparMemoryTotal($user, $hcp); =cut @@ -2552,7 +2686,14 @@ sub getLparMemoryTotal { $sudo = ""; } - my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Info_Query" | grep "real storage"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Info_Query"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo /opt/zhcp/bin/smcli System_Info_Query\"", $hcp, "getLparMemoryTotal", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "real storage"`; my @results = split(' ', $out); return ($results[5]); @@ -2565,7 +2706,7 @@ sub getLparMemoryTotal { Description : Get the offline physical memory of this LPAR Arguments : User (root or non-root) zHCP - Returns : Offline physical memory + Returns : Offline physical memory or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getLparMemoryOffline($user, $hcp); =cut @@ -2579,7 +2720,14 @@ sub getLparMemoryOffline { $sudo = ""; } - my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Info_Query" | grep "real storage"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Info_Query"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo /opt/zhcp/bin/smcli System_Info_Query\"", $hcp, "getLparMemoryOffline", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "real storage"`; my @results = split(' ', $out); return ($results[14]); @@ -2592,7 +2740,7 @@ sub getLparMemoryOffline { Description : Get the used physical memory of this LPAR Arguments : User (root or non-root) zHCP - Returns : Used physical memory + Returns : Used physical memory or string containing (Error)... Example : my $out = xCAT::zvmCPUtils->getLparMemoryUsed($user, $hcp); =cut @@ -2606,7 +2754,14 @@ sub getLparMemoryUsed { $sudo = ""; } - my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Performance_Info_Query " | grep "Used memory pages:"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo /opt/zhcp/bin/smcli System_Performance_Info_Query "`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo /opt/zhcp/bin/smcli System_Performance_Info_Query \"", $hcp, "getLparMemoryUsed", $out ); + if ($rc != 0) { + return $outmsg; + } + $out = `echo "$out" | egrep -a -i "Used memory pages:"`; my @results = split(':', $out); my $page = xCAT::zvmUtils->trimStr( $results[1] ); @@ -3262,7 +3417,7 @@ sub generateUserEntryFile { Description : Obtain the SSI and system status Arguments : User (root or non-root) zHCP - Returns : SSI cluster name + Returns : SSI cluster name or string containing (Error)... Example : my $out = xCAT::zvmUtils->querySSI($user, $hcp); =cut @@ -3279,7 +3434,14 @@ sub querySSI { $sudo = ""; } - my $ssi = `ssh -o ConnectTimeout=10 $user\@$hcp "$sudo $dir/smcli SSI_Query" | egrep -i "ssi_name"`; + my $outmsg; + my $rc; + my $ssi = `ssh -o ConnectTimeout=10 $user\@$hcp "$sudo $dir/smcli SSI_Query"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=10 $user\@$hcp \"$sudo $dir/smcli SSI_Query\"", $hcp, "querySSI", $ssi ); + if ($rc != 0) { + return $outmsg; + } + $ssi = `echo "$ssi" | egrep -a -i "ssi_name"`; $ssi =~ s/ssi_name = //; $ssi =~ s/\s*$//; $ssi =~ s/^\s*//; @@ -3328,7 +3490,7 @@ sub rExecute { Description : Get a list of used FCP devices in the zFCP pools Arguments : User (root or non-root) zHCP - Returns : List of known FCP devices + Returns : List of known FCP devices, or hash with key "Error" containing error message Example : my %devices = xCAT::zvmUtils->getUsedFcpDevices($user, $zhcp); =cut @@ -3348,7 +3510,16 @@ sub getUsedFcpDevices { # Grep the pools for used or allocated zFCP devices my %usedDevices; my @args; - my @devices = split("\n", `ssh $user\@$hcp "$sudo cat $pool/*.conf" | egrep -i "used|allocated"`); + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo cat $pool/*.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo cat $pool/*.conf\"", $hcp, "getUsedFcpDevices", $out ); + if ($rc != 0) { + $usedDevices{"Error"} = $outmsg; + return %usedDevices; + } + $out = `echo "$out" | egrep -a -i "used|allocated"`; + my @devices = split("\n", $out); foreach (@devices) { @args = split(",", $_); @@ -3381,7 +3552,7 @@ sub getUsedFcpDevices { Mount access ('ro' for read only, 'rw' for read write) Directory as known to zHCP (out) Returns : 0 - Mounted, or zHCP and MN are on the same system - 1 - Mount failed + 1 - Mount failed, errors returned in $callback Example : establishMount( $callback, $::SUDOER, $::SUDO, $hcp, $installRoot, $provMethod, "ro", \$remoteDeployDir ); =cut @@ -3426,7 +3597,15 @@ sub establishMount { $$mountedPt = "/mnt/$masterHostname$installRoot/$localDir"; # If the mount point already exists then return because we are done. - my $rc = `ssh $sudoer\@$hcp "$sudo mount | grep $$mountedPt > /dev/null; echo \\\$?"`; + my $outmsg; + my $rc; + $out = `ssh $sudoer\@$hcp "$sudo mount"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $sudoer\@$hcp \"$sudo mount\"", $hcp, "establishMount", $out ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return 1; + } + $rc = `echo "$out" | egrep -a -i $$mountedPt > /dev/null; echo \\\$?"`; if ($rc == 0) { return 0; } @@ -3513,7 +3692,7 @@ sub getFreeRepoSpace { - Owner - Tag Returns : Results hash including: - - Return code (0 = Success, -1 = Failure) + - Return code (0 = Success, -1 = Failure, errors returned in $callback) - zFCP device (if one is requested) - WWPN - LUN @@ -3526,6 +3705,9 @@ sub findAndUpdatezFcpPool { # Get inputs my ($class, $callback, $header, $user, $hcp, $pool, $criteriaRef) = @_; + my $outmsg; + my $rc; + my $out; # Determine if sudo is used my $sudo = "sudo"; if ($user eq "root") { @@ -3614,7 +3796,6 @@ sub findAndUpdatezFcpPool { } # Find disk pool (create one if non-existent) - my $out; if (!(`ssh $user\@$hcp "$sudo test -d $zfcpDir && echo Exists"`)) { # Create pool directory $out = `ssh $user\@$hcp "$sudo mkdir -p $zfcpDir"`; @@ -3639,7 +3820,14 @@ sub findAndUpdatezFcpPool { # used,1000000000000000,2000000000000110,8g,3B00-3B3F,ihost1,1a23,$root_device$ # free,1000000000000000,2000000000000111,,3B00-3B3F,,, # free,1230000000000000;4560000000000000,2000000000000112,,3B00-3B3F,,, - my @devices = split("\n", `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | egrep -i ^free`); + $out = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo cat $zfcpDir/$pool.conf\"", $hcp, "findAndUpdatezFcpPool", $out ); + if ($rc != 0) { + xCAT::zvmUtils->printLn($callback, "$outmsg"); + return \%results; + } + $out = `echo "$out" | egrep -a -i ^free`; + my @devices = split("\n", $out); $sizeFound = 0; foreach (@devices) { @info = split(',', $_); @@ -3677,7 +3865,13 @@ sub findAndUpdatezFcpPool { } } else { # Find given WWPN and LUN. Do not continue if device is used - my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | grep -i "$wwpn,$lun"`; + my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo cat $zfcpDir/$pool.conf\"", $hcp, "findAndUpdatezFcpPool", $select ); + if ($rc != 0) { + xCAT::zvmUtils->printLn($callback, "$outmsg"); + return \%results; + } + $select = `echo "$select" | egrep -a -i "$wwpn,$lun"`; chomp($select); if (!$select) { xCAT::zvmUtils->printLn($callback, "$header: (Error) zFCP device 0x$wwpn/0x$lun could not be found in zFCP pool $pool"); @@ -3724,7 +3918,13 @@ sub findAndUpdatezFcpPool { # Mark WWPN and LUN as used, free, or reserved and set the owner/channel appropriately # This config file keeps track of the owner of each device, which is useful in nodeset $size = $size . "M"; - my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf" | grep -i "$lun"`; + my $select = `ssh $user\@$hcp "$sudo cat $zfcpDir/$pool.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo cat $zfcpDir/$pool.conf\"", $hcp, "findAndUpdatezFcpPool", $select ); + if ($rc != 0) { + xCAT::zvmUtils->printLn($callback, "$outmsg"); + return \%results; + } + $select = `echo "$select" | egrep -a -i "$lun"`; chomp($select); if ($select) { @info = split(',', $select); @@ -3770,7 +3970,7 @@ sub findAndUpdatezFcpPool { candidate FCP devices or auto FCP device range zFCP device owner - Returns : selected FCP device or empty if no one is selected + Returns : selected FCP device or empty if no one is selected, errors returned in $callback Example : my $fcpDevice = xCAT::zvmUtils->selectFcpDevice($callback, $header, $user, $hcp, $fcpDevice, $range, $owner); =cut @@ -3840,12 +4040,24 @@ sub selectFcpDevice { if (!$found) { # If the node has no eligible FCP device, find a free one for it. my %usedDevices = xCAT::zvmUtils->getUsedFcpDevices($user, $hcp); + if (exists $usedDevices{"Error"}) { + xCAT::zvmUtils->printLn($callback, "$header: $usedDevices{Error}"); + return; + } my $hcpUserId = xCAT::zvmCPUtils->getUserId($user, $hcp); $hcpUserId =~ tr/a-z/A-Z/; # Find a free FCP channel - my $out = `ssh $user\@$hcp "$sudo $dir/smcli System_WWPN_Query -T $hcpUserId" | egrep -i "FCP device number|Status"`; + my $outmsg; + my $rc; + my $out = `ssh $user\@$hcp "$sudo $dir/smcli System_WWPN_Query -T $hcpUserId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo $dir/smcli System_WWPN_Query -T $hcpUserId\"", $hcp, "selectFcpDevice", $out ); + if ($rc != 0) { + xCAT::zvmUtils->printLn($callback, "$outmsg"); + return; + } + $out = `echo "$out" | egrep -a -i "FCP device number|Status"`; my @devices = split( "\n", $out ); for (my $i = 0; $i < @devices; $i++) { # Extract the device number and status @@ -3918,7 +4130,7 @@ sub selectFcpDevice { zHCP WWPN LUN - Returns : Storage pool where zFCP device resides + Returns : Storage pool where zFCP device resides, or string containing (Error)... Example : my $pool = xCAT::zvmUtils->findzFcpDevicePool($user, $hcp, $wwpn, $lun); =cut @@ -3938,7 +4150,15 @@ sub findzFcpDevicePool { my $zfcpDir = "/var/opt/zhcp/zfcp"; # Find the pool that contains the SCSI/FCP device - my @pools = split("\n", `ssh $user\@$hcp "$sudo grep -i -l \\\"$wwpn,$lun\\\" $zfcpDir/*.conf"`); + my $out; + my $outmsg; + my $rc; + $out = `ssh $user\@$hcp "$sudo grep -i -l \\\"$wwpn,$lun\\\" $zfcpDir/*.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo grep -i -l \\\"$wwpn,$lun\\\" $zfcpDir/*.conf\"", $hcp, "findzFcpDevicePool", $out ); + if ($rc != 0) { + return $outmsg; + } + my @pools = split("\n", $out); my $pool = ""; if (scalar(@pools)) { $pool = basename($pools[0]); @@ -3958,7 +4178,7 @@ sub findzFcpDevicePool { Storage pool WWPN LUN - Returns : Architecture of node + Returns : Architecture of node or string containing (Error)... Example : my $deviceRef = xCAT::zvmUtils->findzFcpDeviceAttr($user, $hcp, $pool, $wwpn, $lun); =cut @@ -3979,7 +4199,15 @@ sub findzFcpDeviceAttr { # Find the SCSI/FCP device # Entry order: status,wwpn,lun,size,range,owner,channel,tag - my @info = split("\n", `ssh $user\@$hcp "$sudo grep -i \"$wwpn,$lun\" $zfcpDir/$pool.conf"`); + my $out; + my $outmsg; + my $rc; + $out = `ssh $user\@$hcp "$sudo grep -i \"$wwpn,$lun\" $zfcpDir/$pool.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $user\@$hcp \"$sudo grep -i \"$wwpn,$lun\" $zfcpDir/$pool.conf\"", $hcp, "findzFcpDeviceAttr", $out ); + if ($rc != 0) { + return $outmsg; + } + my @info = split("\n", $out); my $entry = $info[0]; chomp($entry); @@ -4479,7 +4707,7 @@ sub execcmdthroughIUCV { } return $result; } elsif ( $rc == 1 ) { - $msg = "IUCV authorized error, error details $result"; + $msg = "Issued command was not authorized or a generic Linux error occurred. error details $result"; push @{$rsp->{data}}, $msg; } elsif ( $rc == 2 ) { $msg = "parameter to iucvclient error, $result"; @@ -4514,7 +4742,7 @@ sub execcmdthroughIUCV { VM's node VM's system - Returns : + Returns : Nothing Example : xCAT::zvmUtils->cleanIUCV( $user, $hcp, $userid); =cut @@ -4541,11 +4769,8 @@ sub cleanIUCV { #clean iucv server file $cmd = "ssh -o ConnectTimeout=5 $user\@$node rm -rf $trgtiucvpath 2>&1"; $result = `ssh -o ConnectTimeout=5 $user\@$node rm -rf $trgtiucvpath 2>&1`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { - xCAT::zvmUtils->printSyslog("$node: SSH to VM to clean iucv server file failed. $result"); - # Continue processing even if an error. - } + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "cleanIUCV", $result, $result, $node ); + # Continue processing even if an error. #clean iucv server service file if ( $os =~ m/sles11/i or $os =~ m/rhel6/i ) { @@ -4563,38 +4788,26 @@ sub cleanIUCV { $cmd = "ssh -o ConnectTimeout=5 $user\@$node rm -rf $trgtiucvservicepath_ubuntu16 2>&1"; $result = `ssh -o ConnectTimeout=5 $user\@$node rm -rf $trgtiucvservicepath_ubuntu16 2>&1`; } - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { - xCAT::zvmUtils->printSyslog("$node: SSH to VM to clean iucv server serivce file failed. $result"); - # Continue processing even if an error. - } + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "cleanIUCV", $result, $node ); + # Continue processing even if an error. #clean iucv server authorized file $cmd = "ssh -o ConnectTimeout=5 $user\@$node rm -rf $trgtiucvpath 2>&1"; $result = `ssh -o ConnectTimeout=5 $user\@$node rm -rf $trgtiucvpath 2>&1`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { - xCAT::zvmUtils->printSyslog("$node: SSH to VM to clean iucv server authorized file failed. $result"); - # Continue processing even if an error. - } + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "cleanIUCV", $result, $node ); + # Continue processing even if an error. #clean iucv server service start if ( $os =~ m/sles11/i or $os =~ m/rhel6/i ){ $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"chkconfig --del iucvserd && service iucvserd stop 2>&1"; $result = `ssh -o ConnectTimeout=5 $user\@$node "chkconfig --del iucvserd && service iucvserd stop 2>&1"`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { - xCAT::zvmUtils->printSyslog("$node: SSH to VM to clean iucv server serivce start failed. $result"); - # Continue processing even if an error. - } + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "cleanIUCV", $result, $node ); + # Continue processing even if an error. }else{ $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"systemctl disable iucvserd.service && systemctl stop iucvserd.service 2>&1"; $result = `ssh -o ConnectTimeout=5 $user\@$node "systemctl disable iucvserd.service && systemctl stop iucvserd.service 2>&1"`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { - xCAT::zvmUtils->printSyslog("$node: SSH to VM to clean iucv server serivce start failed. $result"); - # Continue processing even if an error. - } + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "cleanIUCV", $result, $node ); + # Continue processing even if an error. } } @@ -4643,10 +4856,10 @@ sub setsshforvm { if ($? == 0) { my $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"$commandwithparm\""; $result = `ssh -o ConnectTimeout=5 $user\@$node "$commandwithparm"`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "setsshforvm", $result, $node ); + if ($rc == 255) { if ($isCallback){ - xCAT::zvmUtils->printLn( $callback, "$node: $outmsg"); + xCAT::zvmUtils->printLn( $callback, "$outmsg"); } # Continue processing even if an error. } @@ -4717,6 +4930,7 @@ sub execcmdonVM { my $msg = ''; my $cmd = ''; my $opnclouduserid='OPNCLOUD'; + my $simplecmd = 'date'; # Create path string my $dest = "$user\@$node"; @@ -4740,11 +4954,10 @@ sub execcmdonVM { if (!(defined($userid)) || !(defined($hcp))){ $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"$commandwithparm\""; $result = `ssh -o ConnectTimeout=5 $user\@$node "$commandwithparm"`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { - xCAT::zvmUtils->printSyslog("$node: $cmd $outmsg"); + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "execcmdonVM", $result, $node ); + if ($rc == 255) { if ($isCallback){ - xCAT::zvmUtils->printLn( $callback, "$node: $outmsg"); + xCAT::zvmUtils->printLn( $callback, "$outmsg"); } } # Remove IUCV=1 if it has been set @@ -4763,10 +4976,10 @@ sub execcmdonVM { while ( !$result && $max < 10 ) { $cmd = "ssh $::SUDOER\@$hcp \"$::SUDO /sbin/vmcp q user $userid 2>/dev/null\" | sed 's/HCPCQU045E.*/off/' | sed 's/$userid.*/on/'"; $result = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q user $userid 2>/dev/null" | sed 's/HCPCQU045E.*/off/' | sed 's/$userid.*/on/'`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $hcp, "execcmdonVM", $result, $node ); + if ($rc == 255) { if ($isCallback){ - xCAT::zvmUtils->printLn( $callback, "$node: $outmsg"); + xCAT::zvmUtils->printLn( $callback, "$outmsg"); } return $outmsg; } @@ -4824,11 +5037,10 @@ sub execcmdonVM { # SSH=1, Use ssh to make communication. $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"$commandwithparm\""; $result = `ssh -o ConnectTimeout=5 $user\@$node "$commandwithparm"`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); - if ($rc == -1) { + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "execcmdonVM", $result, $node ); + if ($rc == 255) { if ($isCallback){ - xCAT::zvmUtils->printLn( $callback, "$node: $outmsg"); - xCAT::zvmUtils->printSyslog("$node: $cmd $outmsg"); + xCAT::zvmUtils->printLn( $callback, "$outmsg"); } } return $result; @@ -4902,10 +5114,10 @@ sub execcmdonVM { $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"echo -n $opnclouduserid >$authorizedfilepath\" 2>&1"; $result = `ssh -o ConnectTimeout=5 $user\@$node "echo -n $opnclouduserid >$authorizedfilepath" 2>&1`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "execcmdonVM", $result, $node ); if ($rc != 0) { if ($isCallback){ - xCAT::zvmUtils->printLn( $callback, "$node: $outmsg"); + xCAT::zvmUtils->printLn( $callback, "$outmsg"); } $msg = "echo -n $hcp >$authorizedfilepath, failed to create authorized userid for $node. return $rc $result"; return xCAT::zvmUtils->setsshforvm($user, $node, $os, $commandwithparm, $msg, $status, $callback); @@ -4915,10 +5127,10 @@ sub execcmdonVM { if ( $os =~ m/sles11/i or $os =~ m/rhel6/i ){ $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"chkconfig --add iucvserd && service iucvserd start 2>&1\""; $result = `ssh -o ConnectTimeout=5 $user\@$node "chkconfig --add iucvserd && service iucvserd start 2>&1"`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "execcmdonVM", $result, $node ); if ($rc != 0) { if ($isCallback){ - xCAT::zvmUtils->printLn( $callback, "$node: $outmsg"); + xCAT::zvmUtils->printLn( $callback, "$outmsg"); } $msg = "echo -n $hcp >$authorizedfilepath, failed to create authorized userid for $node. return $rc $result"; return xCAT::zvmUtils->setsshforvm($user, $node, $os, $commandwithparm, $msg, $status, $callback); @@ -4926,10 +5138,10 @@ sub execcmdonVM { }else{ $cmd = "ssh -o ConnectTimeout=5 $user\@$node \"systemctl enable iucvserd.service && systemctl start iucvserd.service 2>&1\""; $result = `ssh -o ConnectTimeout=5 $user\@$node "systemctl enable iucvserd.service && systemctl start iucvserd.service 2>&1"`; - ($rc, $outmsg) = xCAT::zvmUtils->checkSSHOutput( $?, "$cmd" ); + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "$cmd", $node, "execcmdonVM", $result, $node ); if ($rc != 0) { if ($isCallback){ - xCAT::zvmUtils->printLn( $callback, "$node: $outmsg"); + xCAT::zvmUtils->printLn( $callback, "$outmsg"); } $msg = "echo -n $hcp >$authorizedfilepath, failed to create authorized userid for $node. return $rc $result"; return xCAT::zvmUtils->setsshforvm($user, $node, $os, $commandwithparm, $msg, $status, $callback); @@ -4937,8 +5149,10 @@ sub execcmdonVM { } $rc = $? >> 8; xCAT::zvmUtils->printSyslog("$node: start iucvserver service return $rc. $result"); + # Now that the IUCV server has started successfully, send a simple command if ($rc == 0) { - $result = xCAT::zvmUtils->execcmdthroughIUCV($user, $hcp, $userid, $commandwithparm, $callback); + $result = xCAT::zvmUtils->execcmdthroughIUCV($user, $hcp, $userid, $simplecmd, $callback); + # The simple command worked! Update the zvm table so we always communicate via IUCV if ($? == 0){ xCAT::zvmUtils->printSyslog("$node: successfully initialized IUCV, Set IUCV=1 for $user"); if ($callback){ @@ -4950,7 +5164,7 @@ sub execcmdonVM { $status = "IUCV=1"; } xCAT::zvmUtils->setNodeProp( 'zvm', $node, 'status', $status ); - return $result; + return xCAT::zvmUtils->execcmdthroughIUCV($user, $hcp, $userid, $commandwithparm, $callback); }else{ $msg = "$node: Failed to start iucvserver, result is $result"; return xCAT::zvmUtils->setsshforvm($user, $node, $os, $commandwithparm, $msg, $status, $callback); @@ -4959,8 +5173,11 @@ sub execcmdonVM { $msg = "$node: Failed to start iucvserver, result is $result"; return xCAT::zvmUtils->setsshforvm($user, $node, $os, $commandwithparm, $msg, $status, $callback); } + # If our command failed, just return the error + } elsif ($result =~ /Command executed failed/) { + return $result; } else { - $msg = "$node: IUCV server on VM doesn't start well, result is $result"; + $msg = "$node: IUCV server on VM got another error that is not a socket error, result is $result"; return xCAT::zvmUtils->setsshforvm($user, $node, $os, $commandwithparm, $msg, $status, $callback); } } else { diff --git a/xCAT-UI/js/configure/configure.js b/xCAT-UI/js/configure/configure.js index f33e5321f..79cff6f25 100644 --- a/xCAT-UI/js/configure/configure.js +++ b/xCAT-UI/js/configure/configure.js @@ -1,551 +1,558 @@ -/** - * Global variables - */ -var configTabs; // Config tabs -var configDatatables = new Object(); // Datatables on the config page - -/** - * Set the datatable - * - * @param id The ID of the datatable - * @param obj Datatable object - */ -function setConfigDatatable(id, obj) { - configDatatables[id] = obj; -} - -/** - * Get the datatable with the given ID - * - * @param id The ID of the datatable - * @return Datatable object - */ -function getConfigDatatable(id) { - return configDatatables[id]; -} - -/** - * Set the configure tab - * - * @param obj Tab object - */ -function setConfigTab(obj) { - configTabs = obj; -} - -/** - * Get the configure tab - * - * @param Nothing - * @return Tab object - */ -function getConfigTab() { - return configTabs; -} - -/** - * Load configure page - */ -function loadConfigPage() { - // If the configure page has already been loaded - if ($('#content').children().length) { - // Do not reload configure page - return; - } - - // Create configure tab - var tab = new Tab(); - setConfigTab(tab); - tab.init(); - $('#content').append(tab.object()); - - // Create loader - var loader = $('
').append(createLoader()); - - // Add tab to configure xCAT tables - tab.add('configTablesTab', 'Tables', loader, false); - - // Add the self-service tab - tab.add('usersTab', 'Users', '', false); - - // Add the self-service tab - tab.add('serviceTab', 'Service', '', false); - - // Add the files tab - tab.add('filesTab', 'Files', '', false); - - // Get list of tables and their descriptions - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : '-d', - msg : '' - }, - - success : loadTableNames - }); - - // Do not load everything at once - // Load when tab is shown - tab.object().bind('tabsshow', function(event, ui) { - if ($(ui.panel).children().length) { - return; - } - - if (ui.index == 1) { - loadUserPage(); - } else if (ui.index == 2) { - loadServicePage(); - } else if (ui.index == 3) { - loadFilesPage(); - } - }); -} - -/** - * Load xCAT database table names and their descriptions - * - * @param data Data returned from HTTP request - */ -function loadTableNames(data) { - // Get output - var tables = data.rsp; - - // Remove loader - var tabId = 'configTablesTab'; - $('#' + tabId).find('img').hide(); - - // Create a groups division - var tablesDIV = $('
'); - $('#' + tabId).append(tablesDIV); - - // Create info bar - var infoBar = createInfoBar('Select a table to view or edit.'); - tablesDIV.append(infoBar); - - // Create a list for the tables - var list = $(''); - // Loop through each table - for ( var i = 0; i < tables.length; i++) { - // Create a link for each table - var args = tables[i].split(':'); - var link = $('' + args[0] + ''); - - // Open table on click - link.bind('click', function(e) { - // Get table ID that was clicked - var id = (e.target) ? e.target.id : e.srcElement.id; - - // Create loader - var loader = $('
').append(createLoader()); - - // Add a new tab for this table - var configTab = getConfigTab(); - if (!$('#' + id + 'Tab').length) { - configTab.add(id + 'Tab', id, loader, true); - - // Get contents of selected table - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : id, - msg : id - }, - - success : loadTable - }); - } - - // Select new tab - configTab.select(id + 'Tab'); - }); - - var item = $('
  • '); - item.append(link); - - // Append the table description - item.append(': ' + args[1]); - - // Append item to list - list.append(item); - } - - tablesDIV.append(list); -} - -/** - * Load a given database table - * - * @param data Data returned from HTTP request - */ -function loadTable(data) { - // Get response - var rsp = data.rsp; - // Get table ID - var id = data.msg; - - // Remove loader - var tabId = id + 'Tab'; - $('#' + tabId).find('img').remove(); - - // Create info bar - var infoBar = createInfoBar('Click on a cell to edit. Click outside the table to write to the cell. Once you are satisfied with how the table looks, click on Save.'); - $('#' + tabId).append(infoBar); - - // Create action bar - var actionBar = $('
    '); - $('#' + tabId).append(actionBar); - - // Get table headers - var args = rsp[0].replace('#', ''); - var headers = args.split(','); - - // Create container for original table contents - var origCont = new Array(); // Original table content - origCont[0] = rsp[0].split(','); // Headers - - // Create container for new table contents - var newCont = new Object(); - var tmp = new Object(); - tmp[0] = '#' + headers[0]; // Put a # in front of the header - for ( var i = 1; i < headers.length; i++) { - tmp[i] = headers[i]; - } - newCont[0] = tmp; - - // Create a new datatable - var tableId = id + 'Datatable'; - var table = new DataTable(tableId); - - // Add column for the remove row button - headers.unshift(''); - table.init(headers); - headers.shift(); - - // Append datatable to tab - $('#' + tabId).append(table.object()); - - // Add table rows - // Start with the 2nd row (1st row is the headers) - for ( var i = 1; i < rsp.length; i++) { - // Split into columns - var cols = rsp[i].split(','); - - // Go through each column - for ( var j = 0; j < cols.length; j++) { - - // If the column is not complete - if (cols[j].count('"') == 1) { - while (cols[j].count('"') != 2) { - // Merge this column with the adjacent one - cols[j] = cols[j] + "," + cols[j + 1]; - - // Remove merged row - cols.splice(j + 1, 1); - } - } - - // Replace quote - cols[j] = cols[j].replace(new RegExp('"', 'g'), ''); - } - - // Add remove button - cols.unshift(''); - - // Add row - table.add(cols); - - // Save original table content - origCont[i] = cols; - } - - // Turn table into datatable - var dTable = $('#' + id + 'Datatable').dataTable({ - 'iDisplayLength': 50, - 'bLengthChange': false, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - - /** - * Enable editable columns - */ - // Do not make 1st column editable - $('#' + tableId + ' td:not(td:nth-child(1))').editable( - function(value, settings) { - // Get column index - var colPos = this.cellIndex; - // Get row index - var rowPos = dTable.fnGetPosition(this.parentNode); - - // Update datatable - dTable.fnUpdate(value, rowPos, colPos); - - return (value); - }, { - onblur : 'submit', // Clicking outside editable area submits changes - type : 'textarea', - placeholder: ' ', - height : '30px' // The height of the text area - }); - - // Create action bar - var actionBar = $('
    '); - - var saveLnk = $('Save'); - saveLnk.click(function() { - // Get table ID and name - var tableId = $(this).parents('.dataTables_wrapper').attr('id').replace('_wrapper', ''); - var tableName = tableId.replace('Datatable', ''); - - // Get datatable - var dTable = $('#' + tableId).dataTable(); - // Get the nodes from the table - var dRows = dTable.fnGetNodes(); - - // Go through each row - for ( var i = 0; i < dRows.length; i++) { - // If there is row with values - if (dRows[i]) { - // Go through each column - // Ignore the 1st column because it is a button - var cols = dRows[i].childNodes; - var vals = new Object(); - for ( var j = 1; j < cols.length; j++) { - var val = cols.item(j).firstChild.nodeValue; - - // Insert quotes - if (val == ' ') { - vals[j - 1] = ''; - } else { - vals[j - 1] = val; - } - } - - // Save row - newCont[i + 1] = vals; - } - } - - // Update xCAT table - $.ajax({ - type : 'POST', - url : 'lib/tabRestore.php', - dataType : 'json', - data : { - table : tableName, - cont : newCont - }, - success : function(data) { - // Create info message - var dialog = $('
    ').append(createInfoBar('Changes saved!')); - - // Open dialog - dialog.dialog({ - modal: true, - title: 'Info', - width: 400, - buttons: { - "Ok": function(){ - $(this).dialog("close"); - } - } - }); - } - }); - }); - - var undoLnk = $('Undo'); - undoLnk.click(function() { - // Get table ID - var tableId = $(this).parents('.dataTables_wrapper').attr('id').replace('_wrapper', ''); - - // Get datatable - var dTable = $('#' + tableId).dataTable(); - - // Clear entire datatable - dTable.fnClearTable(); - - // Add original content back into datatable - for ( var i = 1; i < origCont.length; i++) { - dTable.fnAddData(origCont[i], true); - } - - // Enable editable columns (again) - // Do not make 1st column editable - $('#' + tableId + ' td:not(td:nth-child(1))').editable( - function(value, settings) { - // Get column index - var colPos = this.cellIndex; - // Get row index - var rowPos = dTable.fnGetPosition(this.parentNode); - - // Update datatable - dTable.fnUpdate(value, rowPos, colPos); - - return (value); - }, { - onblur : 'submit', // Clicking outside editable area submits changes - type : 'textarea', - placeholder: ' ', - height : '30px' // The height of the text area - }); - }); - - var addLnk = $('Add row'); - addLnk.click(function() { - // Create an empty row - var row = new Array(); - - /** - * Remove button - */ - row.push(''); - for ( var i = 0; i < headers.length; i++) { - row.push(''); - } - - // Get table ID and name - var tableId = $(this).parents('.dataTables_wrapper').attr('id').replace('_wrapper', ''); - - // Get datatable - var dTable = $('#' + tableId).dataTable(); - - // Add the row to the data table - dTable.fnAddData(row); - - // Enable editable columns (again) - // Do not make 1st column editable - $('#' + tableId + ' td:not(td:nth-child(1))').editable( - function(value, settings) { - // Get column index - var colPos = this.cellIndex; - // Get row index - var rowPos = dTable.fnGetPosition(this.parentNode); - - // Update datatable - dTable.fnUpdate(value, rowPos, colPos); - - return (value); - }, { - onblur : 'submit', // Clicking outside editable area submits changes - type : 'textarea', - placeholder: ' ', - height : '30px' // The height of the text area - }); - }); - - // Create an action menu - var actionsMenu = createMenu([saveLnk, undoLnk, addLnk]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + id + 'Datatable_wrapper').prepend(menuDiv); - menuDiv.append(actionBar); - $('#' + id + 'Datatable_filter').appendTo(menuDiv); -} - -/** - * Delete a row in the data table - * - * @param obj The object that was clicked - */ -function deleteRow(obj) { - // Get table ID - var tableId = $(obj).parents('table').attr('id'); - - // Get datatable - var dTable = $('#' + tableId).dataTable(); - - // Get all nodes within the datatable - var rows = dTable.fnGetNodes(); - // Get target row - var tgtRow = $(obj).parent().parent().get(0); - - // Find the target row in the datatable - for ( var i in rows) { - // If the row matches the target row - if (rows[i] == tgtRow) { - // Remove row - dTable.fnDeleteRow(i, null, true); - break; - } - } -} - -/** - * Count the number of occurrences of a specific character in a string - * - * @param c Character to count - * @return The number of occurrences - */ -String.prototype.count = function(c) { - return (this.length - this.replace(new RegExp(c, 'g'), '').length)/c.length; -}; - -/** - * Update dialog - * - * @param data HTTP request data - */ -function updatePanel(data) { - var dialogId = data.msg; - var infoMsg; - - // Create info message - if (jQuery.isArray(data.rsp)) { - infoMsg = ''; - for (var i in data.rsp) { - infoMsg += data.rsp[i] + '
    '; - } - } else { - infoMsg = data.rsp; - } - - // Create info bar with close button - var infoBar = $('
    ').css('margin', '5px 0px'); - var icon = $('').css({ - 'display': 'inline-block', - 'margin': '10px 5px' - }); - - // Create close button to close info bar - var close = $('').css({ - 'display': 'inline-block', - 'float': 'right' - }).click(function() { - $(this).parent().remove(); - }); - - var msg = $('
    ' + infoMsg + '
    ').css({ - 'display': 'inline-block', - 'width': '85%' - }); - - infoBar.append(icon, msg, close); - infoBar.prependTo($('#' + dialogId)); +/** + * Global variables + */ +var configTabs; // Config tabs +var configDatatables = new Object(); // Datatables on the config page + +/** + * Set the datatable + * + * @param id The ID of the datatable + * @param obj Datatable object + */ +function setConfigDatatable(id, obj) { + configDatatables[id] = obj; +} + +/** + * Get the datatable with the given ID + * + * @param id The ID of the datatable + * @return Datatable object + */ +function getConfigDatatable(id) { + return configDatatables[id]; +} + +/** + * Set the configure tab + * + * @param obj Tab object + */ +function setConfigTab(obj) { + configTabs = obj; +} + +/** + * Get the configure tab + * + * @param Nothing + * @return Tab object + */ +function getConfigTab() { + return configTabs; +} + +/** + * Load configure page + */ +function loadConfigPage() { + // If the configure page has already been loaded + if ($('#content').children().length) { + // Do not reload configure page + return; + } + + // Create configure tab + var tab = new Tab(); + setConfigTab(tab); + tab.init(); + $('#content').append(tab.object()); + + // Create loader + var loader = $('
    ').append(createLoader()); + + // Add tab to configure xCAT tables + tab.add('configTablesTab', 'Tables', loader, false); + + // Add the self-service tab + tab.add('usersTab', 'Users', '', false); + + // Add the self-service tab + tab.add('serviceTab', 'Service', '', false); + + // Add the files tab + tab.add('filesTab', 'Files', '', false); + + // Get list of tables and their descriptions + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : '-d', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadTableNames(data); + } + }); + + // Do not load everything at once + // Load when tab is shown + tab.object().bind('tabsshow', function(event, ui) { + if ($(ui.panel).children().length) { + return; + } + + if (ui.index == 1) { + loadUserPage(); + } else if (ui.index == 2) { + loadServicePage(); + } else if (ui.index == 3) { + loadFilesPage(); + } + }); +} + +/** + * Load xCAT database table names and their descriptions + * + * @param data Data returned from HTTP request + */ +function loadTableNames(data) { + // Get output + var tables = data.rsp; + + // Remove loader + var tabId = 'configTablesTab'; + $('#' + tabId).find('img').hide(); + + // Create a groups division + var tablesDIV = $('
    '); + $('#' + tabId).append(tablesDIV); + + // Create info bar + var infoBar = createInfoBar('Select a table to view or edit.'); + tablesDIV.append(infoBar); + + // Create a list for the tables + var list = $(''); + // Loop through each table + for ( var i = 0; i < tables.length; i++) { + // Create a link for each table + var args = tables[i].split(':'); + var link = $('' + args[0] + ''); + + // Open table on click + link.bind('click', function(e) { + // Get table ID that was clicked + var id = (e.target) ? e.target.id : e.srcElement.id; + + // Create loader + var loader = $('
    ').append(createLoader()); + + // Add a new tab for this table + var configTab = getConfigTab(); + if (!$('#' + id + 'Tab').length) { + configTab.add(id + 'Tab', id, loader, true); + + // Get contents of selected table + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : id, + msg : id + }, + + success : function(data) { + data = decodeRsp(data); + loadTable(data); + } + }); + } + + // Select new tab + configTab.select(id + 'Tab'); + }); + + var item = $('
  • '); + item.append(link); + + // Append the table description + item.append(': ' + args[1]); + + // Append item to list + list.append(item); + } + + tablesDIV.append(list); +} + +/** + * Load a given database table + * + * @param data Data returned from HTTP request + */ +function loadTable(data) { + // Get response + var rsp = data.rsp; + // Get table ID + var id = data.msg; + + // Remove loader + var tabId = id + 'Tab'; + $('#' + tabId).find('img').remove(); + + // Create info bar + var infoBar = createInfoBar('Click on a cell to edit. Click outside the table to write to the cell. Once you are satisfied with how the table looks, click on Save.'); + $('#' + tabId).append(infoBar); + + // Create action bar + var actionBar = $('
    '); + $('#' + tabId).append(actionBar); + + // Get table headers + var args = rsp[0].replace('#', ''); + var headers = args.split(','); + + // Create container for original table contents + var origCont = new Array(); // Original table content + origCont[0] = rsp[0].split(','); // Headers + + // Create container for new table contents + var newCont = new Object(); + var tmp = new Object(); + tmp[0] = '#' + headers[0]; // Put a # in front of the header + for ( var i = 1; i < headers.length; i++) { + tmp[i] = headers[i]; + } + newCont[0] = tmp; + + // Create a new datatable + var tableId = id + 'Datatable'; + var table = new DataTable(tableId); + + // Add column for the remove row button + headers.unshift(''); + table.init(headers); + headers.shift(); + + // Append datatable to tab + $('#' + tabId).append(table.object()); + + // Add table rows + // Start with the 2nd row (1st row is the headers) + for ( var i = 1; i < rsp.length; i++) { + // Split into columns + var cols = rsp[i].split(','); + + // Go through each column + for ( var j = 0; j < cols.length; j++) { + + // If the column is not complete + if (cols[j].count('"') == 1) { + while (cols[j].count('"') != 2) { + // Merge this column with the adjacent one + cols[j] = cols[j] + "," + cols[j + 1]; + + // Remove merged row + cols.splice(j + 1, 1); + } + } + + // Replace quote + cols[j] = cols[j].replace(new RegExp('"', 'g'), ''); + } + + // Add remove button + cols.unshift(''); + + // Add row + table.add(cols); + + // Save original table content + origCont[i] = cols; + } + + // Turn table into datatable + var dTable = $('#' + id + 'Datatable').dataTable({ + 'iDisplayLength': 50, + 'bLengthChange': false, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + + /** + * Enable editable columns + */ + // Do not make 1st column editable + $('#' + tableId + ' td:not(td:nth-child(1))').editable( + function(value, settings) { + // Get column index + var colPos = this.cellIndex; + // Get row index + var rowPos = dTable.fnGetPosition(this.parentNode); + + // Update datatable + dTable.fnUpdate(value, rowPos, colPos); + + return (value); + }, { + onblur : 'submit', // Clicking outside editable area submits changes + type : 'textarea', + placeholder: ' ', + height : '30px' // The height of the text area + }); + + // Create action bar + var actionBar = $('
    '); + + var saveLnk = $('Save'); + saveLnk.click(function() { + // Get table ID and name + var tableId = $(this).parents('.dataTables_wrapper').attr('id').replace('_wrapper', ''); + var tableName = tableId.replace('Datatable', ''); + + // Get datatable + var dTable = $('#' + tableId).dataTable(); + // Get the nodes from the table + var dRows = dTable.fnGetNodes(); + + // Go through each row + for ( var i = 0; i < dRows.length; i++) { + // If there is row with values + if (dRows[i]) { + // Go through each column + // Ignore the 1st column because it is a button + var cols = dRows[i].childNodes; + var vals = new Object(); + for ( var j = 1; j < cols.length; j++) { + var val = cols.item(j).firstChild.nodeValue; + + // Insert quotes + if (val == ' ') { + vals[j - 1] = ''; + } else { + vals[j - 1] = val; + } + } + + // Save row + newCont[i + 1] = vals; + } + } + + // Update xCAT table + $.ajax({ + type : 'POST', + url : 'lib/tabRestore.php', + dataType : 'json', + data : { + table : tableName, + cont : newCont + }, + success : function(data) { + // data = decodeRsp(data); Do not do this here until tabRestore.php is analyzed + // Create info message + var dialog = $('
    ').append(createInfoBar('Changes saved!')); + + // Open dialog + dialog.dialog({ + modal: true, + title: 'Info', + width: 400, + buttons: { + "Ok": function(){ + $(this).dialog("close"); + } + } + }); + } + }); + }); + + var undoLnk = $('Undo'); + undoLnk.click(function() { + // Get table ID + var tableId = $(this).parents('.dataTables_wrapper').attr('id').replace('_wrapper', ''); + + // Get datatable + var dTable = $('#' + tableId).dataTable(); + + // Clear entire datatable + dTable.fnClearTable(); + + // Add original content back into datatable + for ( var i = 1; i < origCont.length; i++) { + dTable.fnAddData(origCont[i], true); + } + + // Enable editable columns (again) + // Do not make 1st column editable + $('#' + tableId + ' td:not(td:nth-child(1))').editable( + function(value, settings) { + // Get column index + var colPos = this.cellIndex; + // Get row index + var rowPos = dTable.fnGetPosition(this.parentNode); + + // Update datatable + dTable.fnUpdate(value, rowPos, colPos); + + return (value); + }, { + onblur : 'submit', // Clicking outside editable area submits changes + type : 'textarea', + placeholder: ' ', + height : '30px' // The height of the text area + }); + }); + + var addLnk = $('Add row'); + addLnk.click(function() { + // Create an empty row + var row = new Array(); + + /** + * Remove button + */ + row.push(''); + for ( var i = 0; i < headers.length; i++) { + row.push(''); + } + + // Get table ID and name + var tableId = $(this).parents('.dataTables_wrapper').attr('id').replace('_wrapper', ''); + + // Get datatable + var dTable = $('#' + tableId).dataTable(); + + // Add the row to the data table + dTable.fnAddData(row); + + // Enable editable columns (again) + // Do not make 1st column editable + $('#' + tableId + ' td:not(td:nth-child(1))').editable( + function(value, settings) { + // Get column index + var colPos = this.cellIndex; + // Get row index + var rowPos = dTable.fnGetPosition(this.parentNode); + + // Update datatable + dTable.fnUpdate(value, rowPos, colPos); + + return (value); + }, { + onblur : 'submit', // Clicking outside editable area submits changes + type : 'textarea', + placeholder: ' ', + height : '30px' // The height of the text area + }); + }); + + // Create an action menu + var actionsMenu = createMenu([saveLnk, undoLnk, addLnk]); + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); + $('#' + id + 'Datatable_wrapper').prepend(menuDiv); + menuDiv.append(actionBar); + $('#' + id + 'Datatable_filter').appendTo(menuDiv); +} + +/** + * Delete a row in the data table + * + * @param obj The object that was clicked + */ +function deleteRow(obj) { + // Get table ID + var tableId = $(obj).parents('table').attr('id'); + + // Get datatable + var dTable = $('#' + tableId).dataTable(); + + // Get all nodes within the datatable + var rows = dTable.fnGetNodes(); + // Get target row + var tgtRow = $(obj).parent().parent().get(0); + + // Find the target row in the datatable + for ( var i in rows) { + // If the row matches the target row + if (rows[i] == tgtRow) { + // Remove row + dTable.fnDeleteRow(i, null, true); + break; + } + } +} + +/** + * Count the number of occurrences of a specific character in a string + * + * @param c Character to count + * @return The number of occurrences + */ +String.prototype.count = function(c) { + return (this.length - this.replace(new RegExp(c, 'g'), '').length)/c.length; +}; + +/** + * Update dialog + * + * @param data HTTP request data + */ +function updatePanel(data) { + var dialogId = data.msg; + var infoMsg; + + // Create info message + if (jQuery.isArray(data.rsp)) { + infoMsg = ''; + for (var i in data.rsp) { + infoMsg += data.rsp[i] + '
    '; + } + } else { + infoMsg = data.rsp; + } + + // Create info bar with close button + var infoBar = $('
    ').css('margin', '5px 0px'); + var icon = $('').css({ + 'display': 'inline-block', + 'margin': '10px 5px' + }); + + // Create close button to close info bar + var close = $('').css({ + 'display': 'inline-block', + 'float': 'right' + }).click(function() { + $(this).parent().remove(); + }); + + var msg = $('
    ' + infoMsg + '
    ').css({ + 'display': 'inline-block', + 'width': '85%' + }); + + infoBar.append(icon, msg, close); + infoBar.prependTo($('#' + dialogId)); } \ No newline at end of file diff --git a/xCAT-UI/js/configure/files.js b/xCAT-UI/js/configure/files.js index a75eed4a6..4c79af81f 100644 --- a/xCAT-UI/js/configure/files.js +++ b/xCAT-UI/js/configure/files.js @@ -4,43 +4,43 @@ function loadFilesPage() { var tabId = 'filesTab'; $('#' + tabId).empty(); - + // Set padding for page $('#' + tabId).css('padding', '10px 30px'); - + // Create info bar var info = $('#' + tabId).find('.ui-state-highlight'); // If there is no info bar if (!info.length) { var infoBar = createInfoBar('Below is a listing of the xCAT repository. ' + - 'Upload any file or package into the repository using the Upload button. ' + - 'Go into any subdirectories by specifying the directory path and clicking on Go.'); - + 'Upload any file or package into the repository using the Upload button. ' + + 'Go into any subdirectories by specifying the directory path and clicking on Go.'); + var directoryFS = $('
    '); var dirLegend = $('Directory'); directoryFS.append(dirLegend); - + // Division to hold directory actions var actions = $('
    '); directoryFS.append(actions); - + // Create button to create a directory var folderBtn = createButton('New folder'); folderBtn.click(function() { var deleteFolderBtn = $(''); var createFolderBtn = createButton('Create'); - + // Create a new directory var newFolder = $('
  • '); newFolder.prepend(deleteFolderBtn); newFolder.append(createFolderBtn); $('#repo_content ul').append(newFolder); - + // Delete new folder on-click deleteFolderBtn.click(function() { $(this).parents('li').remove(); }); - + // Create folder on-click createFolderBtn.click(function() { var directory = $('#' + tabId + ' input[name="repo_directory"]'); @@ -55,26 +55,27 @@ function loadFilesPage() { args : 'createfolder;' + directory.val() + '/' + newFolderPath, msg : '' }, - + success:function(data) { + data = decodeRsp(data); openDialog('info', data.rsp[0]); } }); - + $(this).parents('li').remove(); } else { openDialog('warn', 'You must specify the folder name'); } }); }); - + // Create button to upload files var uploadBtn = createButton('Upload'); uploadBtn.click(function() { var directory = $('#' + tabId + ' input[name="repo_directory"]'); openUploadDialog(directory.val()); }); - + // Create button to go into a directory path var dirPath = $(''); var goBtn = createButton('Go'); @@ -83,18 +84,18 @@ function loadFilesPage() { loadPath(directory.val()); }); goBtn.attr('id', 'go_to_path'); - + var space = $('
    '); - var content = $('
    '); + var content = $('
    '); actions.append(folderBtn, uploadBtn, dirPath, goBtn); directoryFS.append(space, content); - + $('#' + tabId).append(infoBar, directoryFS); } - - // Retrieve repository space + + // Retrieve repository space getRepositorySpace(); - + // Retrieve files from /install loadPath('/install'); } @@ -115,8 +116,9 @@ function getRepositorySpace() { msg : '' }, success: function(data) { + data = decodeRsp(data); $('#repo_space').children().remove(); - + // Data returned is: size, used, available, used %, mount // Data could be in a different format in CMO, where it puts the directory on the line // "rsp":["\/data\/xcat\/install 28G 6.0G 20G 24% \/install"],"msg":null} @@ -134,7 +136,7 @@ function getRepositorySpace() { /** * Open a dialog to upload files into the repository - * + * * @param destDirectory The destination directory */ function openUploadDialog(destDirectory) { @@ -142,15 +144,15 @@ function openUploadDialog(destDirectory) { var info = createInfoBar('Select a file to upload onto ' + destDirectory + '.'); var dialog = $('
    '); dialog.append(info); - + // Upload file var upload = $('
    '); var label = $(''); var file = $(''); - var subBtn = createButton('Upload'); + var subBtn = createButton('Upload'); upload.append(label, file, subBtn); dialog.append(upload); - + upload.submit(function() { // Create status bar, hide on load var statBarId = 'uploadStatusBar'; @@ -158,8 +160,8 @@ function openUploadDialog(destDirectory) { var loader = createLoader(''); statBar.find('div').append('Do not close this dialog while the file is being uploaded '); statBar.find('div').append(loader); - statBar.prependTo($('#upload_file_dg')); - + statBar.prependTo($('#upload_file_dg')); + var data = new FormData($('#upload_file')[0]); $.ajax({ type: 'POST', @@ -168,8 +170,8 @@ function openUploadDialog(destDirectory) { success: function(data) { $('#uploadStatusBar').find('img').hide(); $('#uploadStatusBar').find('div').empty(); - $('#uploadStatusBar').find('div').append(data); - + $('#uploadStatusBar').find('div').append(data); + // Refresh directory contents $('#go_to_path').click(); getRepositorySpace(); @@ -178,11 +180,11 @@ function openUploadDialog(destDirectory) { contentType: false, processData: false }); - + return false; }); - - // Create dialog + + // Create dialog dialog.dialog({ modal: true, title: 'Upload', @@ -193,7 +195,7 @@ function openUploadDialog(destDirectory) { /** * Load the directory path structure - * + * * @path The directory path */ function loadPath(path) { @@ -202,17 +204,17 @@ function loadPath(path) { openDialog('warn', 'You are not authorized to browse outside the repository'); return; } - + var tabId = 'filesTab'; var directory = $('#' + tabId + ' input[name="repo_directory"]'); directory.val(path); - + // Un-ordered list containing directories and files var contentId = 'repo_content'; $('#' + contentId).empty(); var itemsList = $(''); $('#' + contentId).append(itemsList); - + // Back button to go up a directory var item = $('
  • ..
  • '); itemsList.append(item); @@ -221,7 +223,7 @@ function loadPath(path) { path = path.substring(0, path.lastIndexOf('/')); loadPath(path); }); - + $.ajax({ type: 'POST', url : 'lib/getpath.php', @@ -238,21 +240,21 @@ function loadPath(path) { $.each(files, function(index, file) { if (!file.path || file.path.indexOf("undefined")) file.path = ""; - + var fullPath = file.path + "/" + file.name; - + // Create a list showing the directories and files var item; if (file.isFolder) { var deleteFolderBtn = $(''); - + item = $('
  • ' + file.name + '
  • '); - item.prepend(deleteFolderBtn); + item.prepend(deleteFolderBtn); itemsList.append(item); item.dblclick(function() { loadPath(directory.val() + fullPath); }); - + // Delete file on click deleteFolderBtn.click(function() { deleteFile($(this).parents('li'), directory.val() + fullPath); @@ -260,25 +262,25 @@ function loadPath(path) { } else { var icon = $(''); var deleteFileBtn = $(''); - + item = $('
  • ' + file.name + '
  • '); item.append(deleteFileBtn, icon); - + // Delete file on click deleteFileBtn.click(function() { deleteFile($(this).parents('li'), directory.val() + fullPath); }); - + itemsList.append(item); - } + } }); - } + } }); } /** - * Prompt user to confirm deletion of file - * + * Prompt user to confirm deletion of file + * * @param container The element container * @param file The file name to delete */ @@ -296,14 +298,14 @@ function deleteFile(container, file) { "Ok": function() { var loader = createLoader('').css({'margin': '5px'}); $(this).append(loader); - + // Change dialog buttons $(this).dialog('option', 'buttons', { 'Close':function() { $(this).dialog('destroy').remove(); } }); - + $.ajax({ url : 'lib/cmd.php', dataType : 'json', @@ -315,13 +317,14 @@ function deleteFile(container, file) { msg : '' }, success: function(data) { + data = decodeRsp(data); $('#confirm_delete').children().remove(); var info = createInfoBar(data.rsp[0]); $('#confirm_delete').append(info); getRepositorySpace(); } }); - + // Delete folder from the list container.remove(); }, diff --git a/xCAT-UI/js/configure/service.js b/xCAT-UI/js/configure/service.js index 515b86296..036de8dce 100644 --- a/xCAT-UI/js/configure/service.js +++ b/xCAT-UI/js/configure/service.js @@ -1,1280 +1,1314 @@ -/** - * Global variables - */ -var topPriority = 0; - -/** - * Load the service portal's provision page - * - * @param tabId Tab ID where page will reside - */ -function loadServicePage(tabId) { - // Create info bar - var infoBar = createInfoBar('Select a platform to configure, then click Ok.'); - - // Create self-service portal page - var tabId = 'serviceTab'; - var servicePg = $('
    '); - $('#' + tabId).append(infoBar, servicePg); - - // Create radio buttons for platforms - var hwList = $('
      Platforms available:
    '); - var esx = $('
  • ESX
  • '); - var kvm = $('
  • KVM
  • '); - var zvm = $('
  • z\/VM
  • '); - - hwList.append(esx); - hwList.append(kvm); - hwList.append(zvm); - servicePg.append(hwList); - - /** - * Ok - */ - var okBtn = createButton('Ok'); - okBtn.bind('click', function(event) { - var configTabs = getConfigTab(); - - // Get hardware that was selected - var hw = $(this).parent().find('input[name="hw"]:checked').val(); - var newTabId = hw + 'ProvisionTab'; - - if ($('#' + newTabId).size() > 0){ - configTabs.select(newTabId); - } else { - var title = ''; - - // Create an instance of the plugin - var plugin = null; - switch (hw) { - case "kvm": - plugin = new kvmPlugin(); - title = 'KVM'; - break; - case "esx": - plugin = new esxPlugin(); - title = 'ESX'; - break; - case "zvm": - plugin = new zvmPlugin(); - title = 'z/VM'; - - // Get zVM host names - if (!$.cookie('xcat_zvms')){ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webportal', - tgt : '', - args : 'lszvm', - msg : '' - }, - - success : function(data) { - setzVMCookies(data); - } - }); - } - - break; - } - - // Select tab - configTabs.add(newTabId, title, '', true); - configTabs.select(newTabId); - plugin.loadConfigPage(newTabId); - } - }); - - servicePg.append(okBtn); -} - -/** - * Round a floating point to a given precision - * - * @param value Floating point - * @param precision Decimal precision - * @returns Floating point number - */ -function toFixed(value, precision) { - var power = Math.pow(10, precision || 0); - return String(Math.round(value * power) / power); -} - -/** - * Query the images that exists - * - * @param panelId Panel ID - */ -function queryImages(panelId) { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : 'osimage', - msg : panelId - }, - - success : configImagePanel - }); -} - -/** - * Panel to configure OS images - * - * @param data Data from HTTP request - */ -function configImagePanel(data) { - var panelId = data.msg; - var rsp = data.rsp; - - // Wipe panel clean - $('#' + panelId).empty(); - - // Add info bar - $('#' + panelId).append(createInfoBar('Create, edit, and delete operating system images for the self-service portal.')); - - // Create table - var tableId = panelId + 'Datatable'; - var table = new DataTable(tableId); - table.init(['', 'Name', 'Selectable', 'OS Version', 'OS Arch', 'OS Name', 'Type', 'Profile', 'Method', 'Description']); - - // Insert images into table - var imagePos = 0; - var profilePos = 0; - var osversPos = 0; - var osarchPos = 0; - var osnamePos = 0; - var imagetypePos = 0; - var provMethodPos = 0; - var comments = 0; - var desc, selectable, tmp; - // Get column index for each attribute - 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 'osname':{ - osnamePos = i; - } - break; - - case 'imagetype':{ - imagetypePos = 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 name = 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 osName = cols[osnamePos].replace(new RegExp('"', 'g'), ''); - var imageType = cols[imagetypePos].replace(new RegExp('"', 'g'), ''); - var osComments = cols[comments].replace(new RegExp('"', 'g'), ''); - - // Only save install boot and s390x architectures - if (osArch == "s390x") { - // Set default description and selectable - selectable = "no"; - desc = "No description"; - - if (osComments) { - tmp = osComments.split('|'); - for (var j = 0; j < tmp.length; j++) { - // Save description - if (tmp[j].indexOf('description:') > -1) { - desc = tmp[j].replace('description:', ''); - desc = jQuery.trim(desc); - } - - // Is the image selectable? - if (tmp[j].indexOf('selectable:') > -1) { - selectable = tmp[j].replace('selectable:', ''); - selectable = jQuery.trim(selectable); - } - } - } - - // Columns are: name, selectable, OS version, OS arch, OS name, type, profile, method, and description - var cols = new Array(name, selectable, osVer, osArch, osName, imageType, profile, provMethod, desc); - - // Add remove button where id = user name - cols.unshift(''); - - // Add row - table.add(cols); - } - } - - // Append datatable to tab - $('#' + panelId).append(table.object()); - - // Turn into datatable - $('#' + tableId).dataTable({ - 'iDisplayLength': 50, - 'bLengthChange': false, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - - // Create action bar - var actionBar = $('
    ').css("width", "400px"); - - // Create a profile - var createLnk = $('Create'); - createLnk.click(function() { - imageDialog(); - }); - - // Edit a profile - var editLnk = $('Edit'); - editLnk.click(function() { - var images = $('#' + tableId + ' input[type=checkbox]:checked'); - for (var i in images) { - var image = images.eq(i).attr('name'); - if (image) { - // Columns are: name, selectable, OS version, OS arch, OS name, type, profile, method, and description - var cols = images.eq(i).parents('tr').find('td'); - var selectable = cols.eq(2).text(); - var osVersion = cols.eq(3).text(); - var osArch = cols.eq(4).text(); - var osName = cols.eq(5).text(); - var type = cols.eq(6).text(); - var profile = cols.eq(7).text(); - var method = cols.eq(8).text(); - var description = cols.eq(9).text(); - - editImageDialog(image, selectable, osVersion, osArch, osName, type, profile, method, description); - } - } - }); - - // Delete a profile - var deleteLnk = $('Delete'); - deleteLnk.click(function() { - var images = getNodesChecked(tableId); - if (images) { - deleteImageDialog(images); - } - }); - - // Refresh profiles table - var refreshLnk = $('Refresh'); - refreshLnk.click(function() { - queryImages(panelId); - }); - - // Create an action menu - var actionsMenu = createMenu([refreshLnk, createLnk, editLnk, deleteLnk]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + tableId + '_wrapper').prepend(menuDiv); - menuDiv.append(actionBar); - $('#' + tableId + '_filter').appendTo(menuDiv); - - // Resize accordion - $('#' + tableId).parents('.ui-accordion').accordion('resize'); -} - -/** - * Open image dialog - */ -function imageDialog() { - // Create form to add profile - var dialogId = 'createImage'; - var imageForm = $('
    '); - - // Create info bar - var info = createInfoBar('Provide the following attributes for the image. The image name will be generated based on the attributes you will give.'); - imageForm.append(info); - - var imageName = $('
    '); - var selectable = $('
    '); - var imageType = $('
    '); - var architecture = $('
    '); - var osName = $('
    '); - var osVersion = $('
    '); - var profile = $('
    '); - var provisionMethod = $('
    '); - var provisionSelect = $(''); - provisionMethod.append(provisionSelect); - var comments = $('
    '); - imageForm.append(imageName, selectable, imageType, architecture, osName, osVersion, profile, provisionMethod, comments); - - // Generate tooltips - imageForm.find('div input[title],textarea[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add image - imageForm.dialog({ - title:'Create image', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function() { - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get image attributes - var imageType = $(this).find('input[name="imagetype"]'); - var selectable = $(this).find('input[name="selectable"]'); - var architecture = $(this).find('input[name="osarch"]'); - var osName = $(this).find('input[name="osname"]'); - var osVersion = $(this).find('input[name="osvers"]'); - var profile = $(this).find('input[name="profile"]'); - var provisionMethod = $(this).find('select[name="provmethod"]'); - var comments = $(this).find('input[name="comments"]'); - - // Check that image attributes are provided before continuing - var ready = 1; - var inputs = new Array(imageType, architecture, osName, osVersion, profile, provisionMethod); - for (var i in inputs) { - if (!inputs[i].val()) { - inputs[i].css('border-color', 'red'); - ready = 0; - } else - inputs[i].css('border-color', ''); - } - - // If inputs are not complete, show warning message - if (!ready) { - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this)); - } else { - // Override image name - $(this).find('input[name="imagename"]').val(osVersion.val() + '-' + architecture.val() + '-' + provisionMethod.val() + '-' + profile.val()); - var imageName = $(this).find('input[name="imagename"]'); - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // Set default description - if (!comments.val()) - comments.val('No description'); - - // Create arguments to send via AJAX - var args = 'updateosimage;' + imageName.val() + ';' + - imageType.val() + ';' + - architecture.val() + ';' + - osName.val() + ';' + - osVersion.val() + ';' + - profile.val() + ';' + - provisionMethod.val() + ';'; - - if (selectable.attr('checked')) - args += '"description:' + comments.val() + '|selectable:yes"'; - else - args += '"description:' + comments.val() + '|selectable:no"'; - - // Add image to xCAT - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : args, - msg : dialogId - }, - - success : updatePanel - }); - } - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Edit image dialog - * - * @param iName Image name - * @param iSelectable Is image selectable from service page - * @param iOsVersion OS version - * @param iProfile Profile name - * @param iMethod Provisioning method - * @param iComments Image description - */ -function editImageDialog(iName, iSelectable, iOsVersion, iOsArch, iOsName, iType, iProfile, iMethod, iComments) { - var inst = 0; - var dialogId = 'editImage' + inst; - while ($('#' + dialogId).length) { - // If one already exists, generate another one - inst = inst + 1; - dialogId = 'editImage' + inst; - } - - // Create form to add profile - var imageForm = $('
    '); - - // Create info bar - var info = createInfoBar('Provide the following attributes for the image. The image name will be generated based on the attributes you will give.'); - imageForm.append(info); - - var imageName = $('
    '); - var selectable = $('
    '); - var imageType = $('
    '); - var architecture = $('
    '); - var osName = $('
    '); - var osVersion = $('
    '); - var profile = $('
    '); - var provisionMethod = $('
    '); - var provisionSelect = $(''); - provisionMethod.append(provisionSelect); - var comments = $('
    '); - imageForm.append(imageName, selectable, imageType, architecture, osName, osVersion, profile, provisionMethod, comments); - - // Fill in image attributes - imageForm.find('input[name="imagename"]').val(iName); - imageForm.find('input[name="osvers"]').val(iOsVersion); - imageForm.find('input[name="osarch"]').val(iOsArch); - imageForm.find('input[name="osname"]').val(iOsName); - imageForm.find('input[name="imagetype"]').val(iType); - imageForm.find('input[name="profile"]').val(iProfile); - imageForm.find('select[name="provmethod"]').val(iMethod); - imageForm.find('input[name="comments"]').val(iComments); - if (iSelectable == "yes") - imageForm.find('input[name="selectable"]').attr('checked', 'checked'); - - // Generate tooltips - imageForm.find('div input[title],textarea[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "toggle", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add image - imageForm.dialog({ - title:'Edit image', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function() { - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get image attributes - var imageType = $(this).find('input[name="imagetype"]'); - var selectable = $(this).find('input[name="selectable"]'); - var architecture = $(this).find('input[name="osarch"]'); - var osName = $(this).find('input[name="osname"]'); - var osVersion = $(this).find('input[name="osvers"]'); - var profile = $(this).find('input[name="profile"]'); - var provisionMethod = $(this).find('select[name="provmethod"]'); - var comments = $(this).find('input[name="comments"]'); - - // Check that image attributes are provided before continuing - var ready = 1; - var inputs = new Array(imageType, architecture, osName, osVersion, profile, provisionMethod); - for (var i in inputs) { - if (!inputs[i].val()) { - inputs[i].css('border-color', 'red'); - ready = 0; - } else - inputs[i].css('border-color', ''); - } - - // If inputs are not complete, show warning message - if (!ready) { - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this)); - } else { - // Override image name - $(this).find('input[name="imagename"]').val(osVersion.val() + '-' + architecture.val() + '-' + provisionMethod.val() + '-' + profile.val()); - var imageName = $(this).find('input[name="imagename"]'); - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // Set default description - if (!comments.val()) - comments.val('No description'); - - // Create arguments to send via AJAX - var args = 'updateosimage;' + imageName.val() + ';' + - imageType.val() + ';' + - architecture.val() + ';' + - osName.val() + ';' + - osVersion.val() + ';' + - profile.val() + ';' + - provisionMethod.val() + ';'; - - if (selectable.attr('checked')) - args += '"description:' + comments.val() + '|selectable:yes"'; - else - args += '"description:' + comments.val() + '|selectable:no"'; - - // Add image to xCAT - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : args, - msg : dialogId - }, - - success : updatePanel - }); - } - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Open dialog to confirm image delete - * - * @param images Images to delete - */ -function deleteImageDialog(images) { - // Create form to delete disk to pool - var dialogId = 'deleteImage'; - var deleteForm = $('
    '); - - // Create info bar - var info = createInfoBar('Are you sure you want to delete ' + images.replace(new RegExp(',', 'g'), ', ') + '?'); - deleteForm.append(info); - - // Open dialog to delete user - deleteForm.dialog({ - title:'Delete image', - modal: true, - width: 400, - close: function(){ - $(this).remove(); - }, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // Delete user - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'rmosimage;' + images, - msg : dialogId - }, - success : updatePanel - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Query the groups that exists - * - * @param panelId Panel ID - */ -function queryGroups(panelId) { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : 'hosts', - msg : panelId - }, - - success : configGroupPanel - }); -} - -/** - * Panel to configure groups - * - * @param data Data from HTTP request - */ -function configGroupPanel(data) { - var panelId = data.msg; - var rsp = data.rsp; - - // Wipe panel clean - $('#' + panelId).empty(); - - // Add info bar - $('#' + panelId).append(createInfoBar('Create, edit, and delete groups for the self-service portal.')); - - // Create table - var tableId = panelId + 'Datatable'; - var table = new DataTable(tableId); - table.init(['', 'Name', 'Selectable', 'IP', 'Hostname', 'Description']); - - // Insert groups into table - var nodePos = 0; - var ipPos = 0; - var hostnamePos = 0; - var commentsPos = 0; - var desc, selectable, tmp; - // Get column index for each attribute - var colNameArray = rsp[0].substr(1).split(','); - for (var i in colNameArray){ - switch (colNameArray[i]){ - case 'node': - nodePos = i; - break; - - case 'ip': - ipPos = i; - break; - - case 'hostnames': - hostnamePos = i; - break; - - case 'comments': - commentsPos = 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 name = cols[nodePos].replace(new RegExp('"', 'g'), ''); - var ip = cols[ipPos].replace(new RegExp('"', 'g'), ''); - var hostname = cols[hostnamePos].replace(new RegExp('"', 'g'), ''); - var comments = cols[commentsPos].replace(new RegExp('"', 'g'), ''); - - // Set default description and selectable - selectable = "no"; - network = ""; - desc = "No description"; - - if (comments) { - tmp = comments.split('|'); - for (var j = 0; j < tmp.length; j++) { - // Save description - if (tmp[j].indexOf('description:') > -1) { - desc = tmp[j].replace('description:', ''); - desc = jQuery.trim(desc); - } - - // Is the group selectable? - if (tmp[j].indexOf('selectable:') > -1) { - selectable = tmp[j].replace('selectable:', ''); - selectable = jQuery.trim(selectable); - } - } - } - - // Columns are: name, selectable, network, and description - var cols = new Array(name, selectable, ip, hostname, desc); - - // Add remove button where id = user name - cols.unshift(''); - - // Add row - table.add(cols); - } - - // Append datatable to tab - $('#' + panelId).append(table.object()); - - // Turn into datatable - $('#' + tableId).dataTable({ - 'iDisplayLength': 50, - 'bLengthChange': false, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - - // Create action bar - var actionBar = $('
    ').css("width", "400px"); - - // Create a group - var createLnk = $('Create'); - createLnk.click(function() { - groupDialog(); - }); - - // Edit a group - var editLnk = $('Edit'); - editLnk.click(function() { - var groups = $('#' + tableId + ' input[type=checkbox]:checked'); - for (var i in groups) { - var group = groups.eq(i).attr('name'); - if (group) { - // Column order is: name, selectable, network, and description - var cols = groups.eq(i).parents('tr').find('td'); - var selectable = cols.eq(2).text(); - var ip = cols.eq(3).text(); - var hostnames = cols.eq(4).text(); - var description = cols.eq(5).text(); - - editGroupDialog(group, selectable, ip, hostnames, description); - } - } - }); - - // Delete a profile - var deleteLnk = $('Delete'); - deleteLnk.click(function() { - var groups = getNodesChecked(tableId); - if (groups) { - deleteGroupDialog(groups); - } - }); - - // Refresh profiles table - var refreshLnk = $('Refresh'); - refreshLnk.click(function() { - queryGroups(panelId); - }); - - // Create an action menu - var actionsMenu = createMenu([refreshLnk, createLnk, editLnk, deleteLnk]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + tableId + '_wrapper').prepend(menuDiv); - menuDiv.append(actionBar); - $('#' + tableId + '_filter').appendTo(menuDiv); - - // Resize accordion - $('#' + tableId).parents('.ui-accordion').accordion('resize'); -} - -/** - * Open group dialog - */ -function groupDialog() { - // Create form to add profile - var dialogId = 'createGroup'; - var groupForm = $('
    '); - - // Create info bar - var info = createInfoBar('Provide the following attributes for the group.'); - groupForm.append(info); - - var group = $('
    '); - var selectable = $('
    '); - var ip = $('
    '); - var hostnames = $('
    '); - var comments = $('
    '); - var ipPool = $('
    '); - logOpt.hide(); - optsList.append(logOpt); - - // Create clear log checkbox - var clearChkBox = $('
  • '); - optsList.append(clearChkBox); - clearChkBox.append('Clear log'); - - retrieveChkBox.bind('click', function(event) { - tgtLog.toggle(); - }); - - setChkBox.find('input').bind('click', function(event) { - logOpt.toggle(); - }); - - // Generate tooltips - logForm.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" - } - }); - - /** - * Run node - */ - var runBtn = createButton('Run'); - runBtn.bind('click', function(event) { - // Remove any warning messages - $(this).parent().parent().find('.ui-state-error').remove(); - - var ready = true; - var errMsg = ''; - - // Verify required inputs are provided - var inputs = $('#' + newTabId + ' input'); - for ( var i = 0; i < inputs.length; i++) { - if (!inputs.eq(i).val() - && inputs.eq(i).attr('name') != 'tgtLog' - && inputs.eq(i).attr('name') != 'logOpt') { - inputs.eq(i).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - inputs.eq(i).css('border', 'solid #BDBDBD 1px'); - } - } - - // Write error message - if (!ready) { - errMsg = errMsg + 'Please provide a value for each missing field.
    '; - } - - var tgts = $('#' + newTabId + ' input[name=tgtNode]').val(); - var srcLog = $('#' + newTabId + ' input[name=srcLog]').val(); - - var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); - var optStr = '-s;' + srcLog + ';'; - var opt; - for ( var i = 0; i < chkBoxes.length; i++) { - opt = chkBoxes.eq(i).attr('name'); - optStr += '-' + opt; - - // If it is the retrieve log - if (opt == 't') { - // Append log destination - optStr += ';' + $('#' + newTabId + ' input[name=tgtLog]').val(); - } - - // If it is set options - if (opt == 'o') { - // Append options - optStr += ';' + $('#' + newTabId + ' textarea[name=logOpt]').val(); - } - - // Append ; to end of string - if (i < (chkBoxes.length - 1)) { - optStr += ';'; - } - } - - // If a value is given for every input - if (ready) { - // Do not disable all inputs - //var inputs = $('#' + newTabId + ' input'); - //inputs.attr('disabled', 'disabled'); - - /** - * (1) Retrieve, clear, or set options for event logs - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'reventlog', - tgt : tgts, - args : optStr, - msg : 'out=' + statBarId + ';cmd=reventlog;tgt=' + tgts - }, - - success : updateStatusBar - }); - - // Create loader - $('#' + statBarId).find('div').append(createLoader()); - $('#' + statBarId).show(); - - // Do not disable run button - //$(this).attr('disabled', 'true'); - } else { - // Show warning message - var warn = createWarnBar(errMsg); - warn.prependTo($(this).parent().parent()); - } - }); - logForm.append(runBtn); - - // Add clone tab - tab.add(newTabId, 'Logs', logForm, true); - } - - tab.select(newTabId); -}; +/** + * Execute when the DOM is fully loaded + */ +$(document).ready(function() { + // Load utility scripts + includeJs("js/custom/zvmUtils.js"); +}); + +/** + * Constructor + */ +var zvmPlugin = function() { + +}; + +/** + * Configure self-service configure page + */ +zvmPlugin.prototype.loadConfigPage = function(tabId) { + var configAccordion = $('
    '); + + // Create accordion panel for profiles + var profileSection = $('
    '); + var profileLnk = $('

    Profiles

    ').click(function () { + // Do not load panel again if it is already loaded + if ($('#zvmConfigProfile').find('.dataTables_wrapper').length) + return; + else + $('#zvmConfigProfile').append(createLoader('')); + + queryProfiles('zvmConfigProfile'); + }); + + // Create accordion panel for images + var imgSection = $('
    '); + var imgLnk = $('

    Templates

    ').click(function () { + // Do not load panel again if it is already loaded + if ($('#zvmConfigImages').find('.dataTables_wrapper').length) + return; + else + $('#zvmConfigImages').append(createLoader('')); + + queryImages('zvmConfigImages'); + }); + + // Create accordion panel for groups + var groupsSection = $('
    '); + var groupsLnk = $('

    Groups

    ').click(function () { + // Do not load panel again if it is already loaded + if ($('#zvmConfigGroups').find('.dataTables_wrapper').length) + return; + else + $('#zvmConfigGroups').append(createLoader('')); + + queryGroups('zvmConfigGroups'); + }); + + configAccordion.append(profileLnk, profileSection, imgLnk, imgSection, groupsLnk, groupsSection); + $('#' + tabId).append(configAccordion); + configAccordion.accordion(); + + profileLnk.trigger('click'); +}; + +/** + * Clone node (service page) + * + * @param node Node to clone + */ +zvmPlugin.prototype.serviceClone = function(node) { + var owner = $.cookie('xcat_username'); + var group = getUserNodeAttr(node, 'groups'); + + // Submit request to clone VM + // webportal clonezlinux [src node] [group] [owner] + var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=clonezlinux;' + node + ';' + group + ';' + owner + '&msg=&opts=flush'); + iframe.prependTo($('#manageTab')); +}; + +/** + * Load provision page (service page) + * + * @param tabId Tab ID where page will reside + */ +zvmPlugin.prototype.loadServiceProvisionPage = function(tabId) { + // Create provision form + var provForm = $('
    '); + + // Create info bar + var infoBar = createInfoBar('Provision a Linux virtual machine on IBM z Systems 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 = $(''); + 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, template, and image + var zvmCol = $(''); + provRow.append(zvmCol); + var groupCol = $(''); + provRow.append(groupCol); + var tmplCol = $(''); + provRow.append(tmplCol); + var imgCol = $(''); + provRow.append(imgCol); + + provRow.children('td').css({ + 'min-width': '200px' + }); + + /** + * Provision VM + */ + var provisionBtn = createButton('Provision'); + provisionBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parent().find('.ui-state-error').remove(); + + 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 tmpl = $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]:checked').val(); + var img = $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]:checked').val(); + var owner = $.cookie('xcat_username'); + + if (img && !group) { + // Show warning message + var warn = createWarnBar('You need to select a group'); + warn.prependTo($(this).parent()); + } else if (!img && (!hcp || !group || !tmpl)) { + // Show warning message + var warn = createWarnBar('You need to select a zHCP, group, and image'); + warn.prependTo($(this).parent()); + } else { + if (img) { + // Begin by clonning VM + + // Submit request to clone VM + // webportal clonezlinux [src node] [group] [owner] + var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=clonezlinux;' + img + ';' + group + ';' + owner + '&msg=&opts=flush'); + iframe.prependTo($('#zvmProvisionTab')); + } else { + // Begin by creating VM + createzVM(tabId, group, hcp, tmpl, owner); + } + } + }); + provForm.append(provisionBtn); + + // Load zVMs, groups, template, and image into their respective columns + loadSrvGroups(groupCol); + loadOSImages(tmplCol); + loadGoldenImages(imgCol); + + // Get zVM host names + if (!$.cookie('xcat_zvms')){ + $.ajax( { + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'webportal', + tgt : '', + args : 'lszvm', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setzVMCookies(data); + loadzVMs(zvmCol); + } + }); + } else { + loadzVMs(zvmCol); + } +}; + +/** + * Show node inventory (service page) + * + * @param data Data from HTTP request + */ +zvmPlugin.prototype.loadServiceInventory = function(data) { + var args = data.msg.split(','); + + // Get tab ID + var tabId = args[0].replace('out=', ''); + // Get node + var node = args[1].replace('node=', ''); + + // Remove loader + $('#' + tabId).find('img').remove(); + + // Do not continue if error is found + if (data.rsp[0].indexOf('Error') > -1) { + var warn = createWarnBar(data.rsp[0]); + $('#' + tabId).append(warn); + return; + } + + // Get node inventory + var inv = data.rsp[0].split(node + ':'); + + // Create array of unique property keys for this node (VM) + // The keys must match all possible keys that zvm.pm rinv could return. Can add new ones to the end. + var keys = new Array('userId', 'host', 'os', 'arch', 'uptime', 'cpuusedtime', 'hcp', 'priv', 'memory', 'maxmemory', 'proc', 'disk', 'zfcp', 'nic', 'hypervisornode'); + + // These two arrays show what keys and what order the data is displayed in the GUI + var guikeysGeneral = new Array('userId', 'host', 'hypervisornode', 'os', 'arch', 'uptime'); + var guikeysHardware = new Array('priv', 'memory', 'maxmemory', 'proc', 'disk', 'zfcp', 'nic'); + + // Create hash table for property names (VM) + var attrNames = new Object(); + attrNames['userId'] = 'z/VM UserID:'; + attrNames['host'] = 'z/VM Host:'; + attrNames['os'] = 'Operating System:'; + attrNames['arch'] = 'Architecture:'; + attrNames['uptime'] = 'Uptime:'; + attrNames['cpuusedtime'] = 'CPU Used Time:'; + attrNames['hcp'] = 'HCP:'; + attrNames['priv'] = 'Privileges:'; + attrNames['memory'] = 'Total Memory:'; + attrNames['maxmemory'] = 'Max Memory:'; + attrNames['proc'] = 'Processors:'; + attrNames['disk'] = 'Disks:'; + attrNames['zfcp'] = 'zFCP:'; + attrNames['nic'] = 'NICs:'; + attrNames['hypervisornode'] = 'xCAT Hypervisor Node:'; + + // 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 general property + for ( var k = 0; k < guikeysGeneral.length; k++) { + // Create a list item for each property + item = $('
    1. '); + + // Create a label - Property name. Change old "z/VM Host label" + if (guikeysGeneral[k] == 'host') { + label = ''; + } else { + label = $(''); + } + item.append(label); + + // Insert the data stored in attr hash using the key + for ( var l = 0; l < attrs[guikeysGeneral[k]].length; l++) { + // Create a input - Property value(s) + // Handle each property uniquely + item.append(attrs[guikeysGeneral[k]][l]); + } + + oList.append(item); + } + // Append to inventory form + fieldSet.append(oList); + invDiv.append(fieldSet); + + /** + * Monitoring section + */ + fieldSet = $('
      '); + legend = $('Monitoring [Refresh]'); + fieldSet.append(legend); +// var info = createInfoBar('No data available'); +// fieldSet.append(info.css('width', '300px')); + + getMonitorMetrics(node); + + // Refresh monitoring charts on-click + legend.find('a').click(function() { + 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 = 0; k < guikeysHardware.length; k++) { + // Create a list item + item = $('
      1. '); + + // Create a list to hold the property value(s) + hwList = $(''); + hwItem = $('
      2. '); + + /** + * Privilege section + */ + if (guikeysHardware[k] == 'priv') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Loop through each line + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + // Create a new list item for each line + hwItem = $('
      3. '); + + // Determine privilege + args = attrs[guikeysHardware[k]][l].split(' '); + if (args[0] == 'Directory:') { + label = $(''); + hwItem.append(label); + hwItem.append(args[1]); + } else if (args[0] == 'Currently:') { + label = $(''); + hwItem.append(label); + hwItem.append(args[1]); + } + + hwList.append(hwItem); + } + + item.append(hwList); + } + + /** + * Memory section + */ + else if (guikeysHardware[k] == 'memory') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Loop through each value line + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + // Create a new list item for each line + hwItem = $('
      4. '); + hwItem.append(attrs[guikeysHardware[k]][l]); + hwList.append(hwItem); + } + + item.append(hwList); + } + + /** + * Processor section + */ + else if (guikeysHardware[k] == 'proc') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Create a table to hold processor data + var procTable = $('
        zVM Group Template Image
        '); + var procBody = $(''); + + // Table columns - Type, Address, ID, Base, Dedicated, and Affinity + var procTabRow = $(' Type Address ID Base Dedicated Affinity '); + procTable.append(procTabRow); + var procType, procAddr, procId, procAff; + + // Loop through each processor + var n, temp; + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l]) { + args = attrs[guikeysHardware[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 (guikeysHardware[k] == 'disk') { + // Create a label - Property name + label = $(''); + 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 = $(' Virtual Device # Type VolID Type of Access Size '); + dasdTable.append(dasdTabRow); + var dasdVDev, dasdType, dasdVolId, dasdAccess, dasdSize; + + // Loop through each DASD + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l]) { + args = attrs[guikeysHardware[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); + } + + /** + * zFCP section + */ + else if (guikeysHardware[k] == 'zfcp') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Create a table to hold NIC data + var zfcpTable = $('
        '); + var zfcpBody = $(''); + + // Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name + var zfcpTabRow = $(' Virtual Device # Port Name Unit Number Size'); + zfcpTable.append(zfcpTabRow); + var zfcpVDev, zfcpPortName, zfcpLun, zfcpSize; + + // Loop through each zFCP device + if (attrs[guikeysHardware[k]]) { + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l]) { + args = attrs[guikeysHardware[k]][l].split(' '); + + // Get zFCP virtual device, port name (WWPN), unit number (LUN), and size + zfcpVDev = $('' + args[1].replace('0.0.', '') + ''); + zfcpPortName = $('' + args[4] + ''); + zfcpLun = $('' + args[7] + ''); + zfcpSize = $('' + args[args.length - 2] + ' ' + args[args.length - 1] + ''); + + // Create a new row for each zFCP device + zfcpTabRow = $(''); + zfcpTabRow.append(zfcpVDev); + zfcpTabRow.append(zfcpPortName); + zfcpTabRow.append(zfcpLun); + zfcpTabRow.append(zfcpSize); + + zfcpBody.append(zfcpTabRow); + } + } + } + + zfcpTable.append(zfcpBody); + item.append(zfcpTable); + } + + /** + * NIC section + */ + else if (guikeysHardware[k] == 'nic') { + // Create a label - Property name + label = $(''); + 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 = $('Virtual Device # Adapter Type Port Name # of Devices LAN Name'); + nicTable.append(nicTabRow); + var nicVDev, nicType, nicPortName, nicNumOfDevs, nicLanName; + + // Loop through each NIC (Data contained in 2 lines) + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l].indexOf('Adapter') != -1) { + args = attrs[guikeysHardware[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[guikeysHardware[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); + } + + // Ignore any fields not in key + else { + continue; + } + + 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 clone page + * + * @param node Source node to clone + */ +zvmPlugin.prototype.loadClonePage = function(node, nodeOS, nodeArch) { + // Get nodes tab + if (typeof console == "object"){ + console.log("Entering loadClonePage....."); + } + var tab = getNodesTab(); + var newTabId = node + 'CloneTab'; + + // If there is no existing clone tab + if (!$('#' + newTabId).length) { + // Get table headers + var tableId = $('#' + node).parents('table').attr('id'); + var headers = $('#' + tableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); + var cols = new Array(); + for ( var i = 0; i < headers.length; i++) { + var col = headers.eq(i).text(); + cols.push(col); + } + + // Get hardware control point column + var hcpCol = $.inArray('hcp', cols); + + // Get hardware control point + var nodeRow = $('#' + node).parent().parent(); + var datatable = $('#' + getNodesTableId()).dataTable(); + var rowPos = datatable.fnGetPosition(nodeRow.get(0)); + var aData = datatable.fnGetData(rowPos); + var hcp = aData[hcpCol]; + + // Create status bar and hide it + var statBarId = node + 'CloneStatusBar'; + var statBar = createStatusBar(statBarId).hide(); + + // Create info bar + var infoBar = createInfoBar('Clone a zVM node.'); + + // Create clone form + var cloneForm = $('
        '); + cloneForm.append(statBar); + cloneForm.append(infoBar); + + // Create VM fieldset + var vmFS = $('
        '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + cloneForm.append(vmFS); + + var vmAttr = $('
        '); + vmFS.append($('
        ')); + vmFS.append(vmAttr); + + // Create hardware fieldset + var storageFS = $('
        '); + var storageLegend = $('Storage'); + storageFS.append(storageLegend); + cloneForm.append(storageFS); + + var storageAttr = $('
        '); + storageFS.append($('
        ')); + storageFS.append(storageAttr); + + vmAttr.append('
        '); + vmAttr.append('
        '); + vmAttr.append('
        '); + vmAttr.append('
        '); + + // Create group input + var group = $('
        '); + var groupLabel = $(''); + var groupInput = $(''); + groupInput.one('focus', function(){ + var groupNames = $.cookie('xcat_groups'); + if (groupNames) { + // Turn on auto complete + $(this).autocomplete({ + source: groupNames.split(',') + }); + } + }); + group.append(groupLabel); + group.append(groupInput); + vmAttr.append(group); + + // Create an advanced link to set IP address and hostname + var advancedLnk = $('
        '); + vmAttr.append(advancedLnk); + var advanced = $('
        ').hide(); + vmAttr.append(advanced); + + var ip = $('
        '); + advanced.append(ip); + var hostname = $('
        '); + advanced.append(hostname); + + // Show IP address and hostname inputs on-click + advancedLnk.click(function() { + advanced.toggle(); + }); + + if (typeof console == "object"){ + console.log(" loadClonePage hcp data:<"+hcp+">"); + } + // Get list of disk pools + var temp = hcp.split('.'); + var diskPools = $.cookie('xcat_' + temp[0] + 'diskpools'); + + // Create disk pool input + var poolDiv = $('
        '); + var poolLabel = $(''); + var poolInput = $('').autocomplete({ + source: diskPools.split(',') + }); + poolDiv.append(poolLabel); + poolDiv.append(poolInput); + storageAttr.append(poolDiv); + + storageAttr.append('
        '); + + // Generate tooltips + cloneForm.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" + } + }); + + /** + * Clone node + */ + var cloneBtn = createButton('Clone'); + cloneBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + var ready = true; + var errMsg = ''; + + // Check node name, userId, hardware control point, group, and password + var inputs = $('#' + newTabId + ' input'); + for ( var i = 0; i < inputs.length; i++) { + if (!inputs.eq(i).val() + && inputs.eq(i).attr('name') != 'diskPw' + && inputs.eq(i).attr('name') != 'diskPool' + && inputs.eq(i).attr('name') != 'ip' + && inputs.eq(i).attr('name') != 'hostname') { + inputs.eq(i).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + inputs.eq(i).css('border', 'solid #BDBDBD 1px'); + } + } + + // Write error message + if (!ready) { + errMsg = errMsg + 'Please provide a value for each missing field.
        '; + } + + // Get target node + var nodeRange = $('#' + newTabId + ' input[name=tgtNode]').val(); + // Get target user ID + var userIdRange = $('#' + newTabId + ' input[name=tgtUserId]').val(); + // Get IP address range + var ipRange = $('#' + newTabId + ' input[name=ip]').val(); + // Get hostname range + var hostnameRange = $('#' + newTabId + ' input[name=hostname]').val(); + + // Check node range and user ID range + if (nodeRange.indexOf('-') > -1 || userIdRange.indexOf('-') > -1 || ipRange.indexOf('-') > -1 || hostnameRange.indexOf('-') > -1) { + if (nodeRange.indexOf('-') < 0 || userIdRange.indexOf('-') < 0) { + errMsg = errMsg + 'A user ID range and node range needs to be given.
        '; + ready = false; + } else { + var tmp = nodeRange.split('-'); + + // Get node base name + var nodeBase = tmp[0].match(/[a-zA-Z]+/); + // Get starting index + var nodeStart = parseInt(tmp[0].match(/\d+/)); + // Get ending index + var nodeEnd = parseInt(tmp[1].match(/\d+/)); + + tmp = userIdRange.split('-'); + + // Get user ID base name + var userIdBase = tmp[0].match(/[a-zA-Z]+/); + // Get starting index + var userIdStart = parseInt(tmp[0].match(/\d+/)); + // Get ending index + var userIdEnd = parseInt(tmp[1].match(/\d+/)); + + var ipStart = "", ipEnd = ""; + if (ipRange) { + tmp = ipRange.split('-'); + + // Get starting IP address + ipStart = tmp[0].substring(tmp[0].lastIndexOf(".") + 1); + // Get ending IP address + ipEnd = tmp[1].substring(tmp[1].lastIndexOf(".") + 1); + } + + var hostnameStart = "", hostnameEnd = ""; + if (hostnameRange) { + tmp = hostnameRange.split('-'); + + // Get starting hostname + hostnameStart = parseInt(tmp[0].substring(0, tmp[0].indexOf(".")).match(/\d+/)); + // Get ending hostname + hostnameEnd = parseInt(tmp[1].substring(0, tmp[1].indexOf(".")).match(/\d+/)); + } + + // If starting and ending index do not match + if (!(nodeStart == userIdStart) || !(nodeEnd == userIdEnd)) { + // Not ready to provision + errMsg = errMsg + 'The node range and user ID range does not match.
        '; + ready = false; + } + + // If an IP address range is given and the starting and ending index do not match + if (ipRange && (!(nodeStart == ipStart) || !(nodeEnd == ipEnd))) { + errMsg = errMsg + 'The node range and IP address range does not match. '; + ready = false; + } + + // If a hostname range is given and the starting and ending index do not match + if (hostnameRange && (!(nodeStart == hostnameStart) || !(nodeEnd == hostnameEnd))) { + errMsg = errMsg + 'The node range and hostname range does not match. '; + ready = false; + } + } + } + + // Get source node, hardware control point, group, disk pool, and disk password + var srcNode = $('#' + newTabId + ' input[name=srcNode]').val(); + var hcp = $('#' + newTabId + ' input[name=newHcp]').val(); + var group = $('#' + newTabId + ' input[name=newGroup]').val(); + var diskPool = $('#' + newTabId + ' input[name=diskPool]').val(); + var diskPw = $('#' + newTabId + ' input[name=diskPw]').val(); + + // If a value is given for every input + if (ready) { + // Disable all inputs + var inputs = $('#' + newTabId + ' input'); + inputs.attr('disabled', 'disabled'); + + // If a node range is given + if (nodeRange.indexOf('-') > -1) { + var tmp = nodeRange.split('-'); + + // Get node base name + var nodeBase = tmp[0].match(/[a-zA-Z]+/); + // Get starting index + var nodeStart = parseInt(tmp[0].match(/\d+/)); + // Get ending index + var nodeEnd = parseInt(tmp[1].match(/\d+/)); + + tmp = userIdRange.split('-'); + + // Get user ID base name + var userIdBase = tmp[0].match(/[a-zA-Z]+/); + + var ipBase = ""; + if (ipRange) { + tmp = ipRange.split('-'); + + // Get network base + ipBase = tmp[0].substring(0, tmp[0].lastIndexOf(".") + 1); + } + + var domain = ""; + if (hostnameRange) { + tmp = hostnameRange.split('-'); + + // Get domain name + domain = tmp[0].substring(tmp[0].indexOf(".")); + } + + // Loop through each node in the node range + for ( var i = nodeStart; i <= nodeEnd; i++) { + var node = nodeBase + i.toString(); + var userId = userIdBase + i.toString(); + var inst = i + '/' + nodeEnd; + + var args = node + + ';zvm.hcp=' + hcp + + ';zvm.userid=' + userId + + ';nodehm.mgt=zvm' + + ';nodetype.os=' + nodeOS + + ';nodetype.arch=' + nodeArch + + ';groups=' + group; + + if (ipRange) { + var ip = ipBase + i.toString(); + args += ';hosts.ip=' + ip; + } + + if (hostnameRange) { + var hostname = node + domain; + args += ';hosts.hostnames=' + hostname; + } + + /** + * (1) Define node + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : args, + msg : 'cmd=nodeadd;inst=' + inst + + ';out=' + statBarId + + ';node=' + node + }, + + success : function(data) { + data = decodeRsp(data); + updateZCloneStatus(data); + } + }); + } + } else { + var args = nodeRange + + ';zvm.hcp=' + hcp + + ';zvm.userid=' + userIdRange + + ';nodehm.mgt=zvm' + + ';nodetype.os=' + nodeOS + + ';nodetype.arch=' + nodeArch + + ';groups=' + group; + + if (ipRange) + args += ';hosts.ip=' + ipRange; + + if (hostnameRange) + args += ';hosts.hostnames=' + hostnameRange; + + /** + * (1) Define node + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : args, + msg : 'cmd=nodeadd;inst=1/1;out=' + statBarId + + ';node=' + nodeRange + }, + + success : function(data) { + data = decodeRsp(data); + updateZCloneStatus(data); + } + }); + } + + // Create loader + $('#' + statBarId).find('div').append(createLoader()); + $('#' + statBarId).show(); + + // Disable clone button + $(this).attr('disabled', 'true'); + } else { + // Show warning message + var warn = createWarnBar(errMsg); + warn.prependTo($(this).parent().parent()); + } + }); + cloneForm.append(cloneBtn); + + // Add clone tab + tab.add(newTabId, 'Clone', cloneForm, true); + } + + tab.select(newTabId); +}; + +/** + * Load node inventory + * + * @param data Data from HTTP request + */ +zvmPlugin.prototype.loadInventory = function(data) { + var args = data.msg.split(','); + + // Get tab ID + var tabId = args[0].replace('out=', ''); + // Get node + var node = args[1].replace('node=', ''); + // Clear any existing cookie + $.cookie('xcat_' + node + 'processes', null, {path: '/xcat', secure:true }); + + // Remove loader + $('#' + tabId).find('img').remove(); + + // Check for error + var error = false; + if (data.rsp.length && data.rsp[0].indexOf('Error') > -1) { + error = true; + + var warn = createWarnBar(data.rsp[0]); + $('#' + tabId).append(warn); + } + + // Determine the node type + if (data.rsp.length && data.rsp[0].indexOf('Hypervisor OS:') > -1) { + loadHypervisorInventory(data); + return; + } + + // Create status bar + var statBarId = node + 'StatusBar'; + var statBar = createStatusBar(statBarId); + + // Add loader to status bar and hide it + var loader = createLoader(node + 'StatusBarLoader').hide(); + statBar.find('div').append(loader); + statBar.hide(); + + // Create division to hold user entry + var ueDivId = node + 'UserEntry'; + var ueDiv = $('
        '); + + // Create division to hold inventory + var invDivId = node + 'Inventory'; + var invDiv = $('
        '); + + /** + * Show user entry + */ + var toggleLinkId = node + 'ToggleLink'; + var toggleLink = $('Show directory entry'); + toggleLink.one('click', function(event) { + // Toggle inventory division + $('#' + invDivId).toggle(); + + // Create loader + var loader = createLoader(node + 'TabLoader'); + loader = $('
        ').append(loader); + ueDiv.append(loader); + + // Get user entry + var msg = 'out=' + ueDivId + ';node=' + node; + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : node, + args : '', + msg : msg + }, + + success : function(data) { + data = decodeRsp(data); + loadUserEntry(data); + } + }); + + // Change text + $(this).text('Show inventory'); + + // Disable toggle link + $(this).unbind(event); + }); + + // Align toggle link to the right + var toggleLnkDiv = $('
        ').css({ + 'text-align' : 'right' + }); + toggleLnkDiv.append(toggleLink); + + // Append to tab + $('#' + tabId).append(statBar); + $('#' + tabId).append(toggleLnkDiv); + $('#' + tabId).append(ueDiv); + $('#' + tabId).append(invDiv); + + // Do not load inventory if no inventory is returned + if (data.rsp.length && data.rsp[0].indexOf('z/VM UserID:') > -1) { + // Do nothing + } else { + return; + } + + // Create array of unique property keys for this node (VM) + // The keys must match all possible keys that zvm.pm rinv could return. Can add new ones to the end. + var keys = new Array('userId', 'host', 'os', 'arch', 'uptime', 'cpuusedtime', 'hcp', 'priv', 'memory', 'maxmemory', 'proc', 'disk', 'zfcp', 'nic', 'hypervisornode'); + + // These two arrays show what keys and what order the data is displayed in the GUI + var guikeysGeneral = new Array('userId', 'host', 'hypervisornode', 'os', 'arch', 'uptime', 'cpuusedtime'); + var guikeysHardware = new Array('priv', 'memory', 'maxmemory', 'proc', 'disk', 'zfcp', 'nic'); + + + // Create hash table for property names (VM) + var attrNames = new Object(); + attrNames['userId'] = 'z/VM UserID:'; + attrNames['host'] = 'z/VM Host:'; + attrNames['os'] = 'Operating System:'; + attrNames['arch'] = 'Architecture:'; + attrNames['uptime'] = 'Uptime:'; + attrNames['cpuusedtime'] = 'CPU Used Time:'; + attrNames['hcp'] = 'HCP:'; + attrNames['priv'] = 'Privileges:'; + attrNames['memory'] = 'Total Memory:'; + attrNames['maxmemory'] = 'Max Memory:'; + attrNames['proc'] = 'Processors:'; + attrNames['disk'] = 'Disks:'; + attrNames['zfcp'] = 'zFCP:'; + attrNames['nic'] = 'NICs:'; + attrNames['hypervisornode'] = 'xCAT Hypervisor Node:'; + + // Create hash table for node attributes + var inv = data.rsp[0].split(node + ':'); + var attrs; + if (!error) { + attrs = getAttrs(keys, attrNames, inv); + } + + // Do not continue if error + if (error) { + return; + } + + // Find the hcp node from the host name + // Start off an ajax request to save the zhcp node name + // in a cookie for possible later use by addNic dialog + var hcpHostname = attrs['hcp']; + if (!$.cookie('xcat_' + node+'_hcpnodename')){ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodels', + tgt : 'mgt==zvm', + args : 'hosts.hostnames', + msg : node+';'+hcpHostname + }, + + success : function(data) { + data = decodeRsp(data); + setNodeZhcpNodename(data); + } + }); + } + + /** + * 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 < guikeysGeneral.length; k++) { + // Create a list item for each property + item = $('
        1. '); + + // Create a label - Property name. Change old "z/VM Host label" + if (guikeysGeneral[k] == 'host') { + label = ''; + } else { + label = $(''); + } + item.append(label); + + for (var l = 0; l < attrs[guikeysGeneral[k]].length; l++) { + // Create a input - Property value(s) + // Handle each property uniquely + item.append(attrs[guikeysGeneral[k]][l]); + } + + oList.append(item); + } + // Append to inventory form + fieldSet.append(oList); + invDiv.append(fieldSet); + + /** + * Hardware info section + */ + var hwList, hwItem; + fieldSet = $('
          '); + legend = $('Hardware'); + fieldSet.append(legend); + oList = $('
            '); + + // Loop through each property + var label; + for (k = 0; k < guikeysHardware.length; k++) { + // Create a list item + item = $('
          1. '); + + // Create a list to hold the property value(s) + hwList = $(''); + hwItem = $('
          2. '); + + /** + * Privilege section + */ + if (guikeysHardware[k] == 'priv') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Loop through each line + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + // Create a new list item for each line + hwItem = $('
          3. '); + + // Determine privilege + args = attrs[guikeysHardware[k]][l].split(' '); + if (args[0] == 'Directory:') { + label = $(''); + hwItem.append(label); + hwItem.append(args[1]); + } else if (args[0] == 'Currently:') { + label = $(''); + hwItem.append(label); + hwItem.append(args[1]); + } + + hwList.append(hwItem); + } + + item.append(hwList); + } + + /** + * Memory section + */ + else if (guikeysHardware[k] == 'memory') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Loop through each value line + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + // Create a new list item for each line + hwItem = $('
          4. '); + hwItem.append(attrs[guikeysHardware[k]][l]); + hwList.append(hwItem); + } + + item.append(hwList); + } + + /** + * Processor section + */ + else if (guikeysHardware[k] == 'proc') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Create a table to hold processor data + var procTable = $('
            '); + var procBody = $(''); + var procFooter = $(''); + + // Table columns - Type, Address, ID, Base, Dedicated, and Affinity + var procTabRow = $(' Type Address ID Base Dedicated Affinity '); + procTable.append(procTabRow); + var procId, procAff; + + /** + * Remove processor + */ + var contextMenu = [{ + 'Remove' : function(menuItem, menu) { + var addr = $(this).text(); + + // Open dialog to confirm + var confirmDialog = $('

            Are you sure you want to remove this processor?

            '); + confirmDialog.dialog({ + title: "Confirm", + modal: true, + width: 300, + buttons: { + "Ok": function(){ + removeProcessor(node, addr); + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); + } + }]; + + // Loop through each processor + var n, temp; + var procType, procAddr, procLink; + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l]) { + args = attrs[guikeysHardware[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 = $(''); + procLink = $('' + args[1] + ''); + + // Append context menu to link + procLink.contextMenu(contextMenu, { + theme : 'vista' + }); + + procAddr.append(procLink); + 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); + + /** + * Add processor + */ + var addProcLink = $('+ Add temporary processor'); + addProcLink.bind('click', function(event) { + openAddProcDialog(node); + }); + + procFooter.append(addProcLink); + procTable.append(procFooter); + item.append(procTable); + } + + /** + * Disk section + */ + else if (guikeysHardware[k] == 'disk') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Create a table to hold disk (DASD) data + var dasdTable = $('
            '); + var dasdBody = $(''); + var dasdFooter = $(''); + + /** + * Remove disk + */ + contextMenu = [{ + 'Remove' : function(menuItem, menu) { + var addr = $(this).text(); + + // Open dialog to confirm + var confirmDialog = $('

            Are you sure you want to remove this disk?

            '); + confirmDialog.dialog({ + title: "Confirm", + modal: true, + width: 300, + buttons: { + "Ok": function(){ + removeDisk(node, addr); + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); + } + }]; + + // Table columns - Virtual Device, Type, VolID, Type of Access, and Size + var dasdTabRow = $(' Virtual Device # Type VolID Type of Access Size '); + dasdTable.append(dasdTabRow); + var dasdVDev, dasdType, dasdVolId, dasdAccess, dasdSize; + + // Loop through each DASD + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l]) { + args = attrs[guikeysHardware[k]][l].split(' '); + + // Get DASD virtual device, type, volume ID, access, and size + dasdVDev = $(''); + dasdLink = $('' + args[1] + ''); + + // Append context menu to link + dasdLink.contextMenu(contextMenu, { + theme : 'vista' + }); + dasdVDev.append(dasdLink); + + 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); + + /** + * Add disk + */ + var addDasdLink = $('+ Add disk'); + addDasdLink.bind('click', function(event) { + var hcp = attrs['hcp'][0].split('.'); + openAddDiskDialog(node, hcp[0]); + }); + dasdFooter.append(addDasdLink); + dasdTable.append(dasdFooter); + + item.append(dasdTable); + } + + /** + * zFCP section + */ + else if (guikeysHardware[k] == 'zfcp') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Create a table to hold NIC data + var zfcpTable = $('
            '); + var zfcpBody = $(''); + var zfcpFooter = $(''); + + /** + * Remove zFCP + */ + contextMenu = [ { + 'Remove' : function(menuItem, menu) { + var addr = $(this).text(); + var portName = $(this).parents('tr').find('td:eq(1)').text(); + var unitNo = $(this).parents('tr').find('td:eq(2)').text(); + + // Open dialog to confirm + var confirmDialog = $('

            Are you sure you want to remove this zFCP device?

            '); + confirmDialog.dialog({ + title: "Confirm", + modal: true, + width: 300, + buttons: { + "Ok": function(){ + removeZfcp(node, addr, portName, unitNo); + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); + } + } ]; + + // Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name + var zfcpTabRow = $(' Virtual Device # Port Name Unit Number Size'); + zfcpTable.append(zfcpTabRow); + var zfcpVDev, zfcpPortName, zfcpLun, zfcpSize; + + // Loop through each zFCP device + if (attrs[guikeysHardware[k]]) { + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l]) { + args = attrs[guikeysHardware[k]][l].split(' '); + + // Get zFCP virtual device, port name (WWPN), unit number (LUN), and size + zfcpVDev = $(''); + zfcpLink = $('' + args[1].replace('0.0.', '') + ''); + + // Append context menu to link + zfcpLink.contextMenu(contextMenu, { + theme : 'vista' + }); + zfcpVDev.append(zfcpLink); + + zfcpPortName = $('' + args[4] + ''); + zfcpLun = $('' + args[7] + ''); + zfcpSize = $('' + args[args.length - 2] + ' ' + args[args.length - 1] + ''); + + // Create a new row for each zFCP device + zfcpTabRow = $(''); + zfcpTabRow.append(zfcpVDev); + zfcpTabRow.append(zfcpPortName); + zfcpTabRow.append(zfcpLun); + zfcpTabRow.append(zfcpSize); + + zfcpBody.append(zfcpTabRow); + } + } + } + + zfcpTable.append(zfcpBody); + + /** + * Add dedicated device + */ + var dedicateDeviceLink = $('+ Add dedicated device').css('display', 'block'); + dedicateDeviceLink.bind('click', function(event) { + var hcp = attrs['hcp'][0].split('.'); + openDedicateDeviceDialog(node, hcp[0]); + }); + + /** + * Add zFCP device + */ + var addZfcpLink = $('+ Add zFCP').css('display', 'block'); + addZfcpLink.bind('click', function(event) { + var hcp = attrs['hcp'][0].split('.'); + var zvm = attrs['host'][0].toLowerCase(); + openAddZfcpDialog(node, hcp[0], zvm); + }); + + zfcpFooter.append(dedicateDeviceLink, addZfcpLink); + zfcpTable.append(zfcpFooter); + + item.append(zfcpTable); + } + + /** + * NIC section + */ + else if (guikeysHardware[k] == 'nic') { + // Create a label - Property name + label = $(''); + item.append(label); + + // Create a table to hold NIC data + var nicTable = $('
            '); + var nicBody = $(''); + var nicFooter = $(''); + + /** + * Remove NIC + */ + contextMenu = [ { + 'Remove' : function(menuItem, menu) { + var addr = $(this).text(); + + // Open dialog to confirm + var confirmDialog = $('

            Are you sure you want to remove this NIC?

            '); + confirmDialog.dialog({ + title: "Confirm", + modal: true, + width: 300, + buttons: { + "Ok": function(){ + removeNic(node, addr); + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); + } + } ]; + + // Table columns - Virtual device, Adapter Type, Port Name, # of Devices, MAC Address, and LAN Name + var nicTabRow = $(' Virtual Device # Adapter Type Port Name # of Devices LAN Name'); + nicTable.append(nicTabRow); + var nicVDev, nicType, nicPortName, nicNumOfDevs, nicLanName; + + // Loop through each NIC (Data contained in 2 lines) + for (l = 0; l < attrs[guikeysHardware[k]].length; l++) { + if (attrs[guikeysHardware[k]][l].indexOf('Adapter') != -1) { + args = attrs[guikeysHardware[k]][l].split(' '); + + // Get NIC virtual device, type, port name, and number of devices + nicVDev = $(''); + nicLink = $('' + args[1] + ''); + + // Append context menu to link + nicLink.contextMenu(contextMenu, { + theme : 'vista' + }); + nicVDev.append(nicLink); + + nicType = $('' + args[3] + ''); + nicPortName = $('' + args[10] + ''); + nicNumOfDevs = $('' + args[args.length - 1] + ''); + + args = attrs[guikeysHardware[k]][l + 1].split(' '); + nicLanName = $('' + args[args.length - 2] + ' ' + args[args.length - 1] + ''); + + // Create a new row for each NIC + nicTabRow = $(''); + nicTabRow.append(nicVDev); + nicTabRow.append(nicType); + nicTabRow.append(nicPortName); + nicTabRow.append(nicNumOfDevs); + nicTabRow.append(nicLanName); + + nicBody.append(nicTabRow); + } + } + + nicTable.append(nicBody); + + /** + * Add NIC + */ + var addNicLink = $('+ Add NIC'); + addNicLink.bind('click', function(event) { + //var hcp = attrs['hcp'][0].split('.'); Old Code + // Pass the full zhcp hostname + openAddNicDialog(node, attrs['hcp'][0]); + }); + nicFooter.append(addNicLink); + nicTable.append(nicFooter); + + item.append(nicTable); + } + + // Ignore any fields not in key + else { + continue; + } + + oList.append(item); + } + + // Append inventory to division + fieldSet.append(oList); + invDiv.append(fieldSet); +}; + +/** + * Load hypervisor inventory + * + * @param data Data from HTTP request + */ +function loadHypervisorInventory(data) { + var args = data.msg.split(','); + + // Get tab ID + var tabId = args[0].replace('out=', ''); + // Get node + var node = args[1].replace('node=', ''); + + // Remove loader + $('#' + tabId).find('img').remove(); + + // Check for error + var error = false; + if (data.rsp.length && data.rsp[0].indexOf('Error') > -1) { + error = true; + + var warn = createWarnBar(data.rsp[0]); + $('#' + tabId).append(warn); + } + + // Get node inventory + var inv = data.rsp[0].split(node + ':'); + + // Create status bar + var statBarId = node + 'StatusBar'; + var statBar = createStatusBar(statBarId); + + // Add loader to status bar and hide it + var loader = createLoader(node + 'StatusBarLoader').hide(); + statBar.find('div').append(loader); + statBar.hide(); + + // Create array of property keys (z/VM hypervisor) + // The keys must match all possible keys that zvm.pm rinv for hypervisor could return. Can add new ones to the end. + var keys = new Array('host', 'hcp', 'arch', 'cecvendor', 'cecmodel', 'hypos', 'hypname', 'lparcputotal', 'lparcpuused', 'lparmemorytotal', 'lparmemoryused', 'lparmemoryoffline', 'hypervisornode'); + + // These two arrays show what keys and what order the data is displayed in the GUI + var guikeysGeneral = new Array('host', 'hypervisornode', 'hcp', 'arch', 'arch', 'cecvendor', 'cecmodel', 'hypos', 'hypname'); + var guikeysHardware = new Array('lparcputotal', 'lparcpuused', 'lparmemorytotal', 'lparmemoryused', 'lparmemoryoffline'); + + + // Create hash table for property names (z/VM hypervisor) + var attrNames = new Object(); + attrNames['host'] = 'z/VM Host:'; + attrNames['hcp'] = 'zHCP:'; + attrNames['arch'] = 'Architecture:'; + attrNames['cecvendor'] = 'CEC Vendor:'; + attrNames['cecmodel'] = 'CEC Model:'; + attrNames['hypos'] = 'Hypervisor OS:'; + attrNames['hypname'] = 'Hypervisor Name:'; + attrNames['lparcputotal'] = 'LPAR CPU Total:'; + attrNames['lparcpuused'] = 'LPAR CPU Used:'; + attrNames['lparmemorytotal'] = 'LPAR Memory Total:'; + attrNames['lparmemoryused'] = 'LPAR Memory Used:'; + attrNames['lparmemoryoffline'] = 'LPAR Memory Offline:'; + attrNames['hypervisornode'] = 'xCAT Hypervisor Node:'; + + // Remove loader + $('#' + tabId).find('img').remove(); + + // Create hash table for node attributes + var attrs; + if (!error) { + attrs = getAttrs(keys, attrNames, inv); + } + + // Create division to hold inventory + var invDivId = node + 'Inventory'; + var invDiv = $('
            '); + + // Append to tab + $('#' + tabId).append(statBar); + $('#' + tabId).append(invDiv); + + // Do not continue if error + if (error) { + return; + } + + /** + * 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 < guikeysGeneral.length; k++) { + // Create a list item for each property + item = $('
            1. '); + + // Create a label - Property name. Change old "z/VM Host label" + if (guikeysGeneral[k] == 'host') { + label = ''; + } else { + label = $(''); + } + item.append(label); + + for (var l = 0; l < attrs[guikeysGeneral[k]].length; l++) { + // Create a input - Property value(s) + // Handle each property uniquely + item.append(attrs[guikeysGeneral[k]][l]); + } + + oList.append(item); + } + // Append to inventory form + fieldSet.append(oList); + invDiv.append(fieldSet); + + /** + * Hardware info section + */ + var hwList, hwItem; + fieldSet = $('
              '); + legend = $('Hardware'); + fieldSet.append(legend); + oList = $('
                '); + + // Loop through each property + var label; + for (k = 0; k < guikeysHardware.length; k++) { + // Create a list item for each property + item = $('
              1. '); + + // Create a label - Property name + label = $(''); + item.append(label); + + for (var l = 0; l < attrs[guikeysHardware[k]].length; l++) { + // Create a input - Property value(s) + // Handle each property uniquely + item.append(attrs[guikeysHardware[k]][l]); + } + + oList.append(item); + } + // Append to inventory form + fieldSet.append(oList); + invDiv.append(fieldSet); + + // Append to inventory form + $('#' + tabId).append(invDiv); +}; + +/** + * Load provision page + * + * @param tabId The provision tab ID + */ +zvmPlugin.prototype.loadProvisionPage = function(tabId) { + if (typeof console == "object") { + console.log("Entering loadProvisionPage "); + } + // Get OS image names + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'osimage', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setOSImageCookies(data); + } + }); + + // Get groups + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'extnoderange', + tgt : '/.*', + args : 'subgroups', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setGroupsCookies(data); + } + }); + + // Get provision tab instance + var inst = tabId.replace('zvmProvisionTab', ''); + + // Create provision form + var provForm = $('
                '); + + // Create status bar + var statBarId = 'zProvisionStatBar' + inst; + var statBar = createStatusBar(statBarId).hide(); + provForm.append(statBar); + + // Create loader + var loader = createLoader('zProvisionLoader' + inst).hide(); + statBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('Provision a node on IBM z Systems.'); + provForm.append(infoBar); + + // Append to provision tab + $('#' + tabId).append(provForm); + + var typeFS = $('
                '); + var typeLegend = $('Type'); + typeFS.append(typeLegend); + provForm.append(typeFS); + + // Create provision type drop down + var provType = $('
                '); + var typeLabel = $(''); + var typeSelect = $(''); + var provNewNode = $(''); + var provExistNode = $(''); + typeSelect.append(provNewNode); + typeSelect.append(provExistNode); + provType.append(typeLabel); + provType.append(typeSelect); + typeFS.append(provType); + + /** + * Create provision new node division + */ + var provNew = createZProvisionNew(inst); + provForm.append(provNew); + + /** + * Create provision existing node division + */ + var provExisting = createZProvisionExisting(inst); + provForm.append(provExisting); + + // Toggle provision new/existing on select + typeSelect.change(function(){ + var selected = $(this).val(); + if (selected == 'new') { + provNew.toggle(); + provExisting.toggle(); + } else { + provNew.toggle(); + provExisting.toggle(); + } + }); +}; + +/** + * Load the resources + */ +zvmPlugin.prototype.loadResources = function() { + // Reset resource table + setNetworkDataTable(''); + + // Get hardware control points + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodels', + tgt : 'mgt==zvm', + args : 'zvm.hcp;hosts.hostnames', + msg : '' + }, + success : function(data) { + data = decodeRsp(data); + getZResources(data); + } + }); +}; + +/** + * Add node range + */ +zvmPlugin.prototype.addNode = function() { + // Create form to add node range + var addNodeForm = $('
                '); + var info = createInfoBar('Add a z/VM node range'); + addNodeForm.append(info); + + // Create provision type drop down + var type = $('
                '); + var typeLabel = $(''); + var typeSelect = $(''); + typeSelect.append(''); + typeSelect.append(''); + type.append(typeLabel); + type.append(typeSelect); + addNodeForm.append(type); + + addNodeForm.append('
                '); + addNodeForm.append('
                '); + addNodeForm.append('
                '); + addNodeForm.append('
                '); + addNodeForm.append('
                '); + addNodeForm.append('
                '); + addNodeForm.append('
                '); + addNodeForm.append('
                '); + + // OS field only required for hosts + addNodeForm.find('input[name=os]').parent().hide(); + + // Toggle user Id on select + typeSelect.change(function(){ + var selected = $(this).val(); + if (selected == 'host') { + addNodeForm.find('input[name=userId]').parent().toggle(); + addNodeForm.find('input[name=os]').parent().toggle(); + } else { + addNodeForm.find('input[name=userId]').parent().toggle(); + addNodeForm.find('input[name=os]').parent().toggle(); + } + }); + + // Generate tooltips + addNodeForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open form as a dialog + addNodeForm.dialog({ + title: 'Add node', + modal: true, + width: 400, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var type = $(this).find('select[name=type]').val(); + var nodeRange = $(this).find('input[name=node]').val(); + var ipRange = $(this).find('input[name=ip]').val(); + var hostnameRange = $(this).find('input[name=hostname]').val(); + var userIdRange = $(this).find('input[name=userId]').val(); + var os = $(this).find('input[name=os]').val(); + var group = $(this).find('input[name=groups]').val(); + var hcp = $(this).find('input[name=hcp]').val(); + + // Check required fields + if (type == 'host') { + if (!nodeRange || !os || !group || !hcp) { + var warn = createWarnBar('Please provide a value for each missing field!'); + warn.prependTo($(this)); + return; + } + } else { + if (!nodeRange || !userIdRange || !group || !hcp) { + var warn = createWarnBar('Please provide a value for each missing field!'); + warn.prependTo($(this)); + return; + } + } + + // Check node range and user ID range + // Range can be given as gpok10-gpok20, gpok[10-20], or gpok10+10 + var errMsg = ''; + var ready = true; + if (nodeRange.indexOf('-') > -1 || userIdRange.indexOf('-') > -1) { + if (nodeRange.indexOf('-') < 0 || userIdRange.indexOf('-') < 0) { + errMsg = errMsg + 'A user ID range and node range needs to be given. '; + ready = false; + } else { + var tmp = nodeRange.split('-'); + + // Get starting index + var nodeStart = parseInt(tmp[0].match(/\d+/)); + // Get ending index + var nodeEnd = parseInt(tmp[1].match(/\d+/)); + + tmp = userIdRange.split('-'); + + // Get starting index + var userIdStart = parseInt(tmp[0].match(/\d+/)); + // Get ending index + var userIdEnd = parseInt(tmp[1].match(/\d+/)); + + var ipStart = "", ipEnd = ""; + if (ipRange != "" && ipRange != null) { + tmp = ipRange.split('-'); + + // Get starting IP address + ipStart = tmp[0].substring(tmp[0].lastIndexOf(".") + 1); + // Get ending IP address + ipEnd = tmp[1].substring(tmp[1].lastIndexOf(".") + 1); + } + + var hostnameStart = "", hostnameEnd = ""; + if (hostnameRange != "" && hostnameRange != null) { + tmp = hostnameRange.split('-'); + + // Get starting hostname + hostnameStart = parseInt(tmp[0].substring(0, tmp[0].indexOf(".")).match(/\d+/)); + // Get ending hostname + hostnameEnd = parseInt(tmp[1].substring(0, tmp[1].indexOf(".")).match(/\d+/)); + } + + // If starting and ending index do not match + if (!(nodeStart == userIdStart) || !(nodeEnd == userIdEnd)) { + errMsg = errMsg + 'The node range and user ID range does not match. '; + ready = false; + } + + // If an IP address range is given and the starting and ending index do not match + if (ipRange != "" && ipRange != null && (!(nodeStart == ipStart) || !(nodeEnd == ipEnd))) { + errMsg = errMsg + 'The node range and IP address range does not match. '; + ready = false; + } + + // If a hostname range is given and the starting and ending index do not match + if (hostnameRange != "" && hostnameRange != null && (!(nodeStart == hostnameStart) || !(nodeEnd == hostnameEnd))) { + errMsg = errMsg + 'The node range and hostname range does not match. '; + ready = false; + } + } + } + + // If there are no errors + if (ready) { + $('#addZvm').append(createLoader()); + + // Change dialog buttons + $('#addZvm').dialog('option', 'buttons', { + 'Close':function() { + $('#addZvm').dialog('destroy').remove(); + } + }); + + // If a node range is given + if (nodeRange.indexOf('-') > -1 && userIdRange.indexOf('-') > -1) { + var tmp = nodeRange.split('-'); + + // Get node base name + var nodeBase = tmp[0].match(/[a-zA-Z]+/); + // Get starting index + var nodeStart = parseInt(tmp[0].match(/\d+/)); + // Get ending index + var nodeEnd = parseInt(tmp[1].match(/\d+/)); + + tmp = userIdRange.split('-'); + + // Get user ID base name + var userIdBase = tmp[0].match(/[a-zA-Z]+/); + + var ipBase = ""; + if (ipRange != "" && ipRange != null) { + tmp = ipRange.split('-'); + + // Get network base + ipBase = tmp[0].substring(0, tmp[0].lastIndexOf(".") + 1); + } + + var domain = ""; + if (hostnameRange != "" && hostnameRange != null) { + tmp = hostnameRange.split('-'); + + // Get domain name + domain = tmp[0].substring(tmp[0].indexOf(".")); + } + + // Loop through each node in the node range + for ( var i = nodeStart; i <= nodeEnd; i++) { + var node = nodeBase + i.toString(); + var userId = userIdBase + i.toString(); + var inst = i + '/' + nodeEnd; + + var args = ""; + if (type == 'host') { + args = node + ';zvm.hcp=' + hcp + + ';nodehm.mgt=zvm;nodetype.arch=s390x;hypervisor.type=zvm;groups=' + group + + ';nodetype.os=' + os; + } else { + args = node + ';zvm.hcp=' + hcp + + ';zvm.userid=' + userId + + ';nodehm.mgt=zvm' + ';nodetype.arch=s390x' + ';groups=' + group; + } + + if (ipRange != "" && ipRange != null) { + var ip = ipBase + i.toString(); + args += ';hosts.ip=' + ip; + } + + if (hostnameRange != "" && hostnameRange != null) { + var hostname = node + domain; + args += ';hosts.hostnames=' + hostname; + } + + /** + * (1) Define node + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : args, + msg : 'cmd=addnewnode;inst=' + inst + ';noderange=' + nodeRange + }, + + /** + * Return function on successful AJAX call + * + * @param data + * Data returned from HTTP request + * @return Nothing + */ + success : function (data) { + data = decodeRsp(data); + // Get ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + + // Get instance returned and node range + var inst = args[1].replace('inst=', ''); + var nodeRange = args[2].replace('noderange=', ''); + + // If the last node was added + var tmp = inst.split('/'); + if (tmp[0] == tmp[1]) { + // Update /etc/hosts + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makehosts', + tgt : '', + args : '', + msg : '' + } + }); + + // Remove loader + $('#addZvm img').remove(); + + // If there was an error, do not continue + if (rsp.length) { + $('#addZvm').prepend(createWarnBar('Failed to create node definitions')); + } else { + $('#addZvm').prepend(createInfoBar('Node definitions created for ' + nodeRange)); + } + } + } + }); + } + } else { + var args = ""; + if (type == 'host') { + args = nodeRange + ';zvm.hcp=' + hcp + + ';nodehm.mgt=zvm;nodetype.arch=s390x;hypervisor.type=zvm;groups=' + group + + ';nodetype.os=' + os; + } else { + args = nodeRange + ';zvm.hcp=' + hcp + + ';zvm.userid=' + userIdRange + + ';nodehm.mgt=zvm' + ';nodetype.arch=s390x' + ';groups=' + group; + } + + if (ipRange) + args += ';hosts.ip=' + ipRange; + + if (hostnameRange) + args += ';hosts.hostnames=' + hostnameRange; + + // Only one node to add + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : args, + msg : 'cmd=addnewnode;node=' + nodeRange + }, + + /** + * Return function on successful AJAX call + * + * @param data + * Data returned from HTTP request + * @return Nothing + */ + success : function (data) { + data = decodeRsp(data); + // Get ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + var node = args[1].replace('node=', ''); + + // Update /etc/hosts + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makehosts', + tgt : '', + args : '', + msg : '' + } + }); + + // Remove loader + $('#addZvm img').remove(); + + // If there was an error, do not continue + if (rsp.length) { + $('#addZvm').prepend(createWarnBar('Failed to create node definitions')); + } else { + $('#addZvm').prepend(createInfoBar('Node definitions created for ' + node)); + } + } + }); + } + } else { + // Show warning message + var warn = createWarnBar(errMsg); + warn.prependTo($(this)); + } + }, + "Cancel": function(){ + $(this).dialog('destroy').remove(); + } + } + }); +}; + +/** + * Migrate page + * + * @param tgtNode Targets to migrate + */ +zvmPlugin.prototype.loadMigratePage = function(tgtNode, fromhcp) { + var hosts = $.cookie('xcat_zvms').split(','); + var radio, zvmBlock, args; + var zvms = new Array(); + var hcp = new Object(); + var invalidDest = ''; + if (typeof console == "object"){ + console.log("Entering loadMigratePage. Target nodes:" + tgtNode + " from hcp:" + fromhcp); + } + + // Create a drop-down for z/VM destinations + var destSelect = $('') + for (var i in hosts) { + args = hosts[i].split(':'); // in format of host: zhcp + if (args[0].length > 0) { + hcp[args[0]] = args[1]; + // Only add target systems that are different than the nodes system + if (-1 == fromhcp.search(args[1]) ) { + zvms.push(args[0]); + destSelect.append($('')); + } else { + invalidDest += args[0] + ' '; + } + } + } + + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'migrateTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'migrateTab' + inst; + } + + // Open new tab + // Create remote script form + var migrateForm = $('
                '); + + // Create status bar + var barId = 'migrateStatusBar' + inst; + var statBar = createStatusBar(barId); + statBar.hide(); + migrateForm.append(statBar); + + // Create loader + var loader = createLoader('migrateLoader' + inst); + statBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('The three actions you can perform from this panel are:
                Move -- Initiate a VMRELOCATE of the virtual machine.
                Test - Determine if the specified virtual machine is eligible to be relocated.
                Cancel -- Stop the relocation of the specified virtual machine.'); + migrateForm.append(infoBar); + + // If any destinations were removed, add information message + if (invalidDest.length) { + infoBar.append("
                Ineligible destinations have been removed from the destination list because at least one or more of the nodes selected are already associated with the destinations: " + invalidDest) + } + + // Virtual machine label + var vmFS = $('
                Virtual Machine
                '); + migrateForm.append(vmFS); + + var vmAttr = $('
                '); + vmFS.append($('
                ')); + vmFS.append(vmAttr); + + // Target node or group + var tgt = $('
                '); + vmAttr.append(tgt); + + // Destination + var dest = $('
                '); + var destInput = $(''); + destInput.autocomplete({ + source: zvms + }); + + // Create a drop-down if there are known z/VMs + if (zvms.length) { + dest.append(destSelect); + } else { + dest.append(destInput); + } + vmAttr.append(dest); + + // Action Parameter + var actionparam = $('
                '); + vmAttr.append(actionparam); + + // Parameters label + var optionalFS = $('
                Optional
                ').css('margin-top', '20px'); + migrateForm.append(optionalFS); + + var optAttr = $('
                '); + optionalFS.append($('
                ')); + optionalFS.append(optAttr); + + // Immediate Parameter + var immediateparam = $('
                '); + optAttr.append(immediateparam); + immediateparam.change(function() { + if ($('#' + newTabId + ' select[name=immediate]').val() == 'yes') { + $('#' + newTabId + ' input[name=maxQuiesce]').val('0'); + } else { + $('#' + newTabId + ' input[name=maxQuiesce]').val('10'); + } + }); + + // Max total + var maxTotalParam = $('
                '); + optAttr.append(maxTotalParam); + + // Max quiesce + var maxQuiesceParam = $('
                '); + optAttr.append(maxQuiesceParam); + + // Force parameter + var forceParam = $('
                ArchitectureDomainStorage
                '); + optAttr.append(forceParam); + + // Generate tooltips + migrateForm.find('div input[title],select[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" + } + }); + + /** + * Run + */ + var runBtn = createButton('Run'); + runBtn.click(function() { + // Remove any warning messages + $(this).parent().parent().find('.ui-state-error').remove(); + + var tgt = $('#' + newTabId + ' input[name=target]'); + + // Drop-down box exists if z/VM systems are known + // Otherwise, only input box exists + var dest = $('#' + newTabId + ' select[name=dest]'); + if (!dest.length) { + dest = $('#' + newTabId + ' input[name=dest]'); + } + + var action = $('#' + newTabId + ' select[name=action]'); + var immediate = $('#' + newTabId + ' select[name=immediate]'); + var maxTotal = $('#' + newTabId + ' input[name=maxTotal]'); + var maxQuiesce = $('#' + newTabId + ' input[name=maxQuiesce]'); + var tgts = $('#' + newTabId + ' input[name=target]'); + + // Change borders color back to normal + var inputs = $('#' + newTabId + ' input').css('border', 'solid #BDBDBD 1px'); + var inputs = $('#' + newTabId + ' select').css('border', 'solid #BDBDBD 1px'); + + // Check if required arguments are given + var message = ""; + if (!isInteger(maxTotal.val())) { + message += "Max total time must be an integer. "; + maxTotal.css('border', 'solid #FF0000 1px'); + } if (!isInteger(maxQuiesce.val())) { + message += "Max quiesce time must be an integer. "; + maxQuiesce.css('border', 'solid #FF0000 1px'); + } if (!tgt.val()) { + message += "Target must be specified. "; + tgt.css('border', 'solid #FF0000 1px'); + } if (!dest.val()) { + message += "Destination must be specified. "; + dest.css('border', 'solid #FF0000 1px'); + } if (!action.val()) { + message += "Action must be specified. "; + action.css('border', 'solid #FF0000 1px'); + } + + // Show warning message + if (message) { + var warn = createWarnBar(message); + warn.prependTo($(this).parent().parent()); + return; + } + + var args = "destination=" + dest.val() + ";action=" + action.val() + ";immediate=" + immediate.val() + ";"; + + // Append max total argument. Specified <= 0 to accomodate negative values. + if (maxTotal.val() <= 0) { + args = args + "max_total=NOLIMIT;"; + } else { + args = args + "max_total=" + maxTotal.val() + ";"; + } + + // Append max quiesce argument. Specified <= 0 to accomodate negative values. + if (maxQuiesce.val() <= 0) { + args = args + "max_quiesce=NOLIMIT;"; + } else { + args = args + "max_quiesce=" + maxQuiesce.val() + ";"; + } + + // Append force argument + if ($("input[name=force]:checked").length > 0) { + args = args + "'force=" + $("input[name=force]:checked").each(function() { + args += $(this).val() + ' '; + }); + args += "';"; + } + + var statBarId = 'migrateStatusBar' + inst; + $('#' + statBarId).show(); + + // Disable all fields + $('#' + newTabId + ' input').attr('disabled', 'true'); + $('#' + newTabId + ' select').attr('disabled', 'true'); + + // Disable buttons + $('#' + newTabId + ' button').attr('disabled', 'true'); + + // Run migrate + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rmigrate', + tgt : tgts.val(), + args : args, + msg : 'out=migrateStatusBar' + inst + ';cmd=rmigrate;tgt=' + tgts.val() + }, + + success : function(data) { + data = decodeRsp(data); + updateStatusBar(data); + } + }); + }); + migrateForm.append(runBtn); + + // Append to discover tab + tab.add(newTabId, 'Migrate', migrateForm, true); + + // Select new tab + tab.select(newTabId); +}; + +/** + * Load event log configuration page + * + * @param node Source node to clone + */ +zvmPlugin.prototype.loadLogPage = function(node) { + // Get nodes tab + var tab = getNodesTab(); + var newTabId = node + 'LogsTab'; + + // If there is no existing clone tab + if (!$('#' + newTabId).length) { + // Get table headers + var tableId = $('#' + node).parents('table').attr('id'); + var headers = $('#' + tableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); + var cols = new Array(); + for ( var i = 0; i < headers.length; i++) { + var col = headers.eq(i).text(); + cols.push(col); + } + + // Get hardware control point column + var hcpCol = $.inArray('hcp', cols); + + // Get hardware control point + var nodeRow = $('#' + node).parent().parent(); + var datatable = $('#' + getNodesTableId()).dataTable(); + var rowPos = datatable.fnGetPosition(nodeRow.get(0)); + var aData = datatable.fnGetData(rowPos); + var hcp = aData[hcpCol]; + + // Create status bar and hide it + var statBarId = node + 'CloneStatusBar'; + var statBar = createStatusBar(statBarId).hide(); + + // Create info bar + var infoBar = createInfoBar('Retrieve, clear, or set options for event logs.'); + + // Create clone form + var logForm = $('
                '); + logForm.append(statBar); + logForm.append(infoBar); + + // Create VM fieldset + var vmFS = $('
                '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + logForm.append(vmFS); + + var vmAttr = $('
                '); + vmFS.append($('
                ')); + vmFS.append(vmAttr); + + // Create logs fieldset + var logFS = $('
                '); + var logLegend = $('Logs'); + logFS.append(logLegend); + logForm.append(logFS); + + var logAttr = $('
                '); + logFS.append($('
                ')); + logFS.append(logAttr); + + vmAttr.append('
                '); + logAttr.append('
                '); + + var optsLabel = $(''); + var optsList = $('
                  '); + logAttr.append(optsLabel); + logAttr.append(optsList); + + // Create retrieve log checkbox + var retrieveChkBox = $('
                • '); + optsList.append(retrieveChkBox); + retrieveChkBox.append('Retrieve log'); + + // Create log destination input + var tgtLog = $('
                • '); + tgtLog.hide(); + optsList.append(tgtLog); + + // Create set log checkbox + var setChkBox = $('
                • '); + optsList.append(setChkBox); + setChkBox.append('Set options'); + + // Create log options input + var logOpt = $('
                • '); + logOpt.hide(); + optsList.append(logOpt); + + // Create clear log checkbox + var clearChkBox = $('
                • '); + optsList.append(clearChkBox); + clearChkBox.append('Clear log'); + + retrieveChkBox.bind('click', function(event) { + tgtLog.toggle(); + }); + + setChkBox.find('input').bind('click', function(event) { + logOpt.toggle(); + }); + + // Generate tooltips + logForm.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" + } + }); + + /** + * Run node + */ + var runBtn = createButton('Run'); + runBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parent().parent().find('.ui-state-error').remove(); + + var ready = true; + var errMsg = ''; + + // Verify required inputs are provided + var inputs = $('#' + newTabId + ' input'); + for ( var i = 0; i < inputs.length; i++) { + if (!inputs.eq(i).val() + && inputs.eq(i).attr('name') != 'tgtLog' + && inputs.eq(i).attr('name') != 'logOpt') { + inputs.eq(i).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + inputs.eq(i).css('border', 'solid #BDBDBD 1px'); + } + } + + // Write error message + if (!ready) { + errMsg = errMsg + 'Please provide a value for each missing field.
                  '; + } + + var tgts = $('#' + newTabId + ' input[name=tgtNode]').val(); + var srcLog = $('#' + newTabId + ' input[name=srcLog]').val(); + + var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); + var optStr = '-s;' + srcLog + ';'; + var opt; + for ( var i = 0; i < chkBoxes.length; i++) { + opt = chkBoxes.eq(i).attr('name'); + optStr += '-' + opt; + + // If it is the retrieve log + if (opt == 't') { + // Append log destination + optStr += ';' + $('#' + newTabId + ' input[name=tgtLog]').val(); + } + + // If it is set options + if (opt == 'o') { + // Append options + optStr += ';' + $('#' + newTabId + ' textarea[name=logOpt]').val(); + } + + // Append ; to end of string + if (i < (chkBoxes.length - 1)) { + optStr += ';'; + } + } + + // If a value is given for every input + if (ready) { + // Do not disable all inputs + //var inputs = $('#' + newTabId + ' input'); + //inputs.attr('disabled', 'disabled'); + + /** + * (1) Retrieve, clear, or set options for event logs + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'reventlog', + tgt : tgts, + args : optStr, + msg : 'out=' + statBarId + ';cmd=reventlog;tgt=' + tgts + }, + + success : function(data) { + data = decodeRsp(data); + updateStatusBar(data); + } + }); + + // Create loader + $('#' + statBarId).find('div').append(createLoader()); + $('#' + statBarId).show(); + + // Do not disable run button + //$(this).attr('disabled', 'true'); + } else { + // Show warning message + var warn = createWarnBar(errMsg); + warn.prependTo($(this).parent().parent()); + } + }); + logForm.append(runBtn); + + // Add clone tab + tab.add(newTabId, 'Logs', logForm, true); + } + + tab.select(newTabId); +}; diff --git a/xCAT-UI/js/custom/zvmUtils.js b/xCAT-UI/js/custom/zvmUtils.js index 3ff044834..8af844457 100644 --- a/xCAT-UI/js/custom/zvmUtils.js +++ b/xCAT-UI/js/custom/zvmUtils.js @@ -1,8140 +1,8345 @@ -/*"use strict"; */ -/** - * Global variables - */ -var diskDatatable; // zVM datatable containing disks -var zfcpDatatable; // zVM datatable containing zFCP devices -var networkDatatable; // zVM datatable containing networks -var builtInXCAT = 1; // 1 means xCAT shipped with zVM -var zhcpQueryCountForDisks = 0; -var zhcpQueryCountForZfcps = 0; -var zhcpQueryCountForNetworks = 0; -var selectedNetworkHash; // Network details for each network - -/** - * Get the disk datatable - * - * @return Data table object - */ -function getDiskDataTable() { - return diskDatatable; -} - -/** - * Set the disk datatable - * - * @param table Data table object - */ -function setDiskDataTable(table) { - diskDatatable = table; -} - -/** - * Get the zFCP datatable - * - * @return Data table object - */ -function getZfcpDataTable() { - return zfcpDatatable; -} - -/** - * Set the zFCP datatable - * - * @param table Data table object - */ -function setZfcpDataTable(table) { - zfcpDatatable = table; -} - -/** - * Get the network datatable - * - * @return Data table object - */ -function getNetworkDataTable() { - return networkDatatable; -} - -/** - * Set the network datatable - * - * @param table Data table object - */ -function setNetworkDataTable(table) { - networkDatatable = table; -} - -/** - * Get the selectedNetworkHash datatable - * - * @return selectedNetworkHash two dimensional hash table object - */ -function getselectedNetworkHash() { - return selectedNetworkHash; -} - -/** - * Set the selectedNetworkHash two dimensional hash table - * - * @param table selectedNetworkHash object - */ -function setselectedNetworkHash(table) { - selectedNetworkHash = table; -} - -/** - * Display hcp node pool lookup finished - */ -function displayNodeHcpFinished(count){ - var infoBar = getNodesTabInfoBar(); - if (infoBar !== null) { - if (count <= 0) { - infoBar.append(" Done."); - }else { - infoBar.append(" ."); - } - } -} - -/** - * Load HCP specific info - * - * @param data Data from HTTP request - */ -function loadHcpInfo(data) { - var args = data.msg.split(';'); - var findingPools = 0; - var findingPoolsCount = 0; - - // Get group - var group = args[0].replace('group=', ''); - // Get hardware control point - var hcp = args[1].replace('hcp=', ''); - - // Get user directory entry - var userEntry = data.rsp; - if (!userEntry.length) - return; - - // Get Nodes info bar - var nodeInfoBar = getNodesTabInfoBar(); - //nodeInfoBar.append("\nEntering loadHcpInfo Load...\n"); - - if (userEntry[0].indexOf('Failed') < 0) { - if (hcp) { - // If there is no cookie for the disk pool names - if (!$.cookie('xcat_' + hcp + 'diskpools') || $.cookie('xcat_' + hcp + 'diskpools') === null) { - if (nodeInfoBar !== null) { - nodeInfoBar.append("
                  Finding pools and networks..."); - findingPools = 1; - findingPoolsCount++; - } - // Get disk pools - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcp, - args : '--diskpoolnames', - msg : hcp - }, - - success : setDiskPoolCookies, - complete : function() { - if (nodeInfoBar !== null) { - findingPoolsCount--; - displayNodeHcpFinished(findingPoolsCount); - } - } - }); - } - - // If there is no cookie for the zFCP pool names - if (!$.cookie('xcat_' + hcp + 'zfcppools') || $.cookie('xcat_' + hcp + 'zfcppools') === null) { - - if (nodeInfoBar !== null) { - if (findingPools = 0) { - nodeInfoBar.append("
                  Finding pools and networks..."); - } - findingPools = 1; - findingPoolsCount++; - } - // Get fcp pools - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcp, - args : '--zfcppoolnames', - msg : hcp - }, - - success : setZfcpPoolCookies, - complete : function() { - if (nodeInfoBar !== null) { - findingPoolsCount--; - displayNodeHcpFinished(findingPoolsCount); - } - } - }); - } - - // If there is no cookie for the network names - if (!$.cookie('xcat_' + hcp + 'networks') || $.cookie('xcat_' + hcp + 'networks') === null) { - - if (nodeInfoBar !== null) { - if (findingPools = 0) { - nodeInfoBar.append("
                  Finding pools and networks..."); - } - findingPools = 1; - findingPoolsCount++; - } - // Get network names - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcp, - args : '--getnetworknames', - msg : hcp - }, - - success : setNetworkCookies, - complete : function() { - if (nodeInfoBar !== null) { - findingPoolsCount--; - displayNodeHcpFinished(findingPoolsCount); - } - } - }); - } - } // End of if (hcp) - } else { - // Create warning dialog - var warning = createWarnBar('z/VM SMAPI is not responding to ' + hcp + '. SMAPI may need to be reset. '+userEntry[0]); - var warnDialog = $('
                  ').append(warning); - - // Open dialog - warnDialog.dialog({ - title:'Warning', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function() { - $(this).dialog("close"); - } - } - }); - } -} - -/** - * Load user entry of a given node - * - * @param data Data from HTTP request - */ -function loadUserEntry(data) { - var args = data.msg.split(';'); - - // Get tab ID - var ueDivId = args[0].replace('out=', ''); - // Get node - var node = args[1].replace('node=', ''); - // Get user directory entry - var userEntry = data.rsp[0].split(node + ':'); - - // Remove loader - $('#' + node + 'TabLoader').remove(); - - var toggleLinkId = node + 'ToggleLink'; - $('#' + toggleLinkId).click(function() { - // Get text within this link - var lnkText = $(this).text(); - - // Toggle user entry division - $('#' + node + 'UserEntry').toggle(); - // Toggle inventory division - $('#' + node + 'Inventory').toggle(); - - // Change text - if (lnkText == 'Show directory entry') { - $(this).text('Show inventory'); - } else { - $(this).text('Show directory entry'); - } - }); - - // Put user entry into a list - var fieldSet = $('
                  '); - var legend = $('Directory Entry'); - fieldSet.append(legend); - - var txtArea = $(''); - for ( var i = 1; i < userEntry.length; i++) { - userEntry[i] = jQuery.trim(userEntry[i]); - txtArea.append(userEntry[i]); - - if (i < userEntry.length) { - txtArea.append('\n'); - } - } - txtArea.attr('readonly', 'readonly'); - fieldSet.append(txtArea); - - /** - * Edit user entry - */ - txtArea.bind('dblclick', function(event) { - txtArea.attr('readonly', ''); - txtArea.css( { - 'border-width' : '1px' - }); - - saveBtn.show(); - cancelBtn.show(); - saveBtn.css('display', 'inline-table'); - cancelBtn.css('display', 'inline-table'); - }); - - /** - * Save - */ - var saveBtn = createButton('Save').hide(); - saveBtn.bind('click', function(event) { - // Show loader - $('#' + node + 'StatusBarLoader').show(); - $('#' + node + 'StatusBar').show(); - - // Replace user entry - var newUserEntry = jQuery.trim(txtArea.val()) + '\n'; - - // Replace user entry - $.ajax( { - url : 'lib/zCmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--replacevs', - att : newUserEntry, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process and save it in a cookie - incrementNodeProcess(node); - - txtArea.attr('readonly', 'readonly'); - txtArea.css( { - 'border-width' : '0px' - }); - - // Disable save button - $(this).hide(); - cancelBtn.hide(); - }); - - /** - * Cancel - */ - var cancelBtn = createButton('Cancel').hide(); - cancelBtn.bind('click', function(event) { - txtArea.attr('readonly', 'readonly'); - txtArea.css( { - 'border-width' : '0px' - }); - - cancelBtn.hide(); - saveBtn.hide(); - }); - - // Create info bar - var infoBar = createInfoBar('Double click on the directory entry to edit it.'); - - // Append user entry into division - $('#' + ueDivId).append(infoBar); - $('#' + ueDivId).append(fieldSet); - $('#' + ueDivId).append(saveBtn); - $('#' + ueDivId).append(cancelBtn); -} - -/** - * Increment number of processes running against a node - * - * @param node Node to increment running processes - */ -function incrementNodeProcess(node) { - // Get current processes - var procs = $.cookie('xcat_' + node + 'processes'); - if (procs) { - // One more process - procs = parseInt(procs) + 1; - $.cookie('xcat_' + node + 'processes', procs); - } else { - $.cookie('xcat_' + node + 'processes', 1); - } -} - -/** - * Update provision new node status - * - * @param data Data returned from HTTP request - */ -function updateZProvisionNewStatus(data) { - // Parse ajax response - var rsp = data.rsp; - var args = data.msg.split(';'); - var lastCmd = args[0].replace('cmd=', ''); - var out2Id = args[1].replace('out=', ''); - if (typeof console == "object"){ - console.log("Entering updateZProvisionNewStatus. Last command:<"+lastCmd+"> All args:<"+args+">"); - } - // IDs for status bar, tab, and loader - var statBarId = 'zProvisionStatBar' + out2Id; - var tabId = 'zvmProvisionTab' + out2Id; - var loaderId = 'zProvisionLoader' + out2Id; - - var node = $('#' + tabId + ' input[name=nodeName]').val(); - - /** - * (2) Create user entry - */ - if (lastCmd == 'nodeadd') { - if (rsp.length) { - $('#' + loaderId).hide(); - $('#' + statBarId).find('div').append('
                  (Error) Failed to create node definition
                  '); - } else { - $('#' + statBarId).find('div').append('
                  Node definition created for ' + node + '
                  '); - - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - - // Create user entry - var userEntry = $('#' + tabId + ' textarea').val(); - $.ajax( { - url : 'lib/zCmd.php', - dataType : 'json', - data : { - cmd : 'mkvm', - tgt : node, - args : '', - att : userEntry, - msg : 'cmd=mkvm;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - - /** - * (3) Update /etc/hosts - */ - else if (lastCmd == 'mkvm') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - - // If there was an error, quit - if (containErrors(prg.html())) { - $('#' + loaderId).hide(); - } else { - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'makehosts', - tgt : '', - args : '', - msg : 'cmd=makehosts;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - - /** - * If sourceforge xcat: (4) Update DNS - */ - else if ((lastCmd == 'makehosts') && (builtInXCAT == 0)) { - // If there was an error, quit - if (rsp.length) { - $('#' + loaderId).hide(); - $('#' + statBarId).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); - } else { - $('#' + statBarId).find('div').append('
                  /etc/hosts updated
                  '); - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'makedns', - tgt : '', - args : '', - msg : 'cmd=makedns;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - /** - * If built in zVM xcat and last command was makehosts or - * If sourceforge xCAT and lastCmd was makedns - * (5) Add disk - * - */ - else if (((lastCmd == 'makehosts') && (builtInXCAT == 1)) || - ((lastCmd == 'makedns') && (builtInXCAT == 0))) { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - - // If there was an error, quit - if (rsp.length) { - $('#' + loaderId).hide(); - if (builtInXCAT == 1) { - $('#' + statBarId).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); - } else { - $('#' + statBarId).find('div').append('
                  (Error) Failed to makedns
                  '); - } - } else { - if (builtInXCAT == 1) { - $('#' + statBarId).find('div').append('
                  /etc/hosts updated
                  '); - } else { - $('#' + statBarId).find('div').append('
                  makedns updated
                  '); - } - - // Set cookie for number of disks - var diskRows = $('#' + tabId + ' table:eq(0):visible tbody tr'); - $.cookie('xcat_disks2add' + out2Id, diskRows.length, {path: '/xcat', secure:true }); - if (diskRows.length > 0) { - for (var i = 0; i < diskRows.length; i++) { - var diskArgs = diskRows.eq(i).find('td'); - var type = diskArgs.eq(1).find('select').val(); - var address = diskArgs.eq(2).find('input').val(); - var size = diskArgs.eq(3).find('input').val(); - var mode = diskArgs.eq(4).find('select').val(); - var pool = diskArgs.eq(5).find('select').val(); - var password = diskArgs.eq(6).find('input').val(); - - // Create ajax arguments - var args = ''; - if (type == '3390') { - args = '--add' + type + ';' + pool + ';' + address - + ';' + size + ';' + mode + ';' + password + ';' - + password + ';' + password; - } else if (type == '9336') { - args = '--add' + type + ';' + pool + ';' + address + ';' - + size + ';' + mode + ';' + password + ';' - + password + ';' + password; - } - - // Attach disk to node - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : args, - msg : 'cmd=chvm-disk;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - - // Set cookie for number of zFCP devices - var zfcpRows = $('#' + tabId + ' table:eq(1):visible tbody tr'); - $.cookie('xcat_zfcp2add' + out2Id, zfcpRows.length, {path: '/xcat', secure:true }); - if (zfcpRows.length > 0) { - for ( var i = 0; i < zfcpRows.length; i++) { - var diskArgs = zfcpRows.eq(i).find('td'); - var address = diskArgs.eq(1).find('input').val(); - var size = diskArgs.eq(2).find('input').val(); - var pool = diskArgs.eq(3).find('select').val(); - var tag = diskArgs.eq(4).find('input').val(); - var portName = diskArgs.eq(5).find('input').val(); - var unitNo = diskArgs.eq(6).find('input').val(); - - // This is either true or false - var loaddev = diskArgs.eq(7).find('input').attr('checked'); - if (loaddev) { - loaddev = "1"; - } else { - loaddev = "0"; - } - - // Create ajax arguments - var args = '--addzfcp;' + pool + ';' + address + ';' + loaddev + ';' + size; - if (tag && tag != "null") { - args += ';' + tag; - } else { - args += ';'; - } if (portName && tag != "null") { - args += ';' + portName; - } else { - args += ';'; - } if (unitNo && tag != "null") { - args += ';' + unitNo; - } else { - args += ';'; - } - - // Attach zFCP device to node - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : args, - msg : 'cmd=chvm-zfcp;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - - // Done if no disks to add - if (diskRows.length < 1 && zfcpRows.length < 1) { - $('#' + statBarId).find('div').append('
                  No disks found to provison, finished.
                  '); - $('#' + loaderId).hide(); - } - } - } - - /** - * (6) Set operating system for given node - */ - else if (lastCmd == 'chvm-disk' || lastCmd == 'chvm-zfcp') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - - // If there was an error, quit - if (containErrors(prg.html())) { - $('#' + loaderId).hide(); - } else { - // Set cookie for number of disks - // One less disk to add - var disks2add = $.cookie('xcat_disks2add' + out2Id); - if (lastCmd == 'chvm-disk') { - if (disks2add > 0) { - disks2add--; - $.cookie('xcat_disks2add' + out2Id, disks2add, {path: '/xcat', secure:true }); - } - } - - var zfcp2add = $.cookie('xcat_zfcp2add' + out2Id); - if (lastCmd == 'chvm-zfcp') { - if (zfcp2add > 0) { - zfcp2add--; - $.cookie('xcat_zfcp2add' + out2Id, zfcp2add, {path: '/xcat', secure:true }); - } - } - - // Only set operating system if there are no more disks to add - if (zfcp2add < 1 && disks2add < 1) { - // If an operating system image is given - var osImage = $('#' + tabId + ' select[name=os]:visible').val(); - if (osImage) { - // Get operating system, architecture, provision method, and profile - var tmp = osImage.split('-'); - var os = tmp[0]; - var arch = tmp[1]; - var profile = tmp[3]; - - // If the last disk is added - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeadd', - tgt : '', - args : node + ';noderes.netboot=zvm;nodetype.os=' - + os + ';nodetype.arch=' + arch - + ';nodetype.profile=' + profile, - msg : 'cmd=noderes;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } else { - $('#' + loaderId).hide(); - } - } - } - } - - /** - * (7) If sourceforge xCAT Update DHCP - */ - else if ((lastCmd == 'noderes') && (builtInXCAT == 0)) { - // If there was an error, do not continue - if (rsp.length) { - $('#' + loaderId).hide(); - $('#' + statBarId).find('div').append('
                  (Error) Failed to set operating system
                  '); - } else { - $('#' + statBarId).find('div').append('
                  Operating system for ' + node + ' set
                  '); - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'makedhcp', - tgt : '', - args : '-a', - msg : 'cmd=makedhcp;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - - /** - * (8) Prepare node for boot - */ - else if (((lastCmd == 'noderes') && (builtInXCAT == 1)) || - ((lastCmd == 'makedhcp') && (builtInXCAT == 0))) { - // If there was an error, do not continue - if (rsp.length) { - $('#' + loaderId).hide(); - if (builtInXCAT == 1) { - $('#' + statBarId).find('div').append('
                  (Error) Failed to set operating system
                  '); - } else { - $('#' + statBarId).find('div').append('
                  (Error) Failed to make dhcp
                  '); - } - } else { - if (builtInXCAT == 1) { - $('#' + statBarId).find('div').append('
                  Operating system for ' + node + ' set
                  '); - } else { - $('#' + statBarId).find('div').append('
                  DHCP for ' + node + ' set
                  '); - } - - // Prepare node for boot - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeset', - tgt : node, - args : 'install', - msg : 'cmd=nodeset;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - - /** - * (9) Boot node to network - */ - else if (lastCmd == 'nodeset') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - - // If there was an error - // Do not continue - if (containErrors(prg.html())) { - $('#' + loaderId).hide(); - } else { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'rnetboot', - tgt : node, - args : 'ipl=000C', - msg : 'cmd=rnetboot;out=' + out2Id - }, - - success : updateZProvisionNewStatus - }); - } - } - - /** - * (10) Done - */ - else if (lastCmd == 'rnetboot') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - if (prg.html().indexOf('Error') < 0) { - $('#' + statBarId).find('div').append('
                  Open a VNC viewer to see the installation progress.  It might take a couple of minutes before you can connect.
                  '); - } - - // Hide loader - $('#' + loaderId).hide(); - } -} - -/** - * Update the provision existing node status - * - * @param data Data returned from HTTP request - */ -function updateZProvisionExistingStatus(data) { - // Get ajax response - var rsp = data.rsp; - var args = data.msg.split(';'); - - // Get command invoked - var cmd = args[0].replace('cmd=', ''); - // Get provision tab instance - var inst = args[1].replace('out=', ''); - if (typeof console == "object"){ - console.log("Entering updateZProvisionExistingStatus. Last command:<"+cmd+"> All args:<"+args+">"); - } - - // Get provision tab and status bar ID - var statBarId = 'zProvisionStatBar' + inst; - var tabId = 'zvmProvisionTab' + inst; - - /** - * (2) Prepare node for boot - */ - if (cmd == 'nodeadd') { - // Get operating system - var bootMethod = $('#' + tabId + ' select[name=bootMethod]').val(); - - // Get nodes that were checked - var dTableId = 'zNodesDatatable' + inst; - var tgts = getNodesChecked(dTableId); - - // Prepare node for boot - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeset', - tgt : tgts, - args : bootMethod, - msg : 'cmd=nodeset;out=' + inst - }, - - success : updateZProvisionExistingStatus - }); - } - - /** - * (3) Boot node from network - */ - else if (cmd == 'nodeset') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - - // If there was an error, do not continue - if (containErrors(prg.html())) { - var loaderId = 'zProvisionLoader' + inst; - $('#' + loaderId).remove(); - return; - } - - // Get nodes that were checked - var dTableId = 'zNodesDatatable' + inst; - var tgts = getNodesChecked(dTableId); - - // Boot node from network - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'rnetboot', - tgt : tgts, - args : 'ipl=000C', - msg : 'cmd=rnetboot;out=' + inst - }, - - success : updateZProvisionExistingStatus - }); - } - - /** - * (4) Done - */ - else if (cmd == 'rnetboot') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - if (prg.html().indexOf('Error') < 0) { - $('#' + statBarId).find('div').append('
                  Open a VNC viewer to see the installation progress.  It might take a couple of minutes before you can connect.
                  '); - } - - var loaderId = 'zProvisionLoader' + inst; - $('#' + loaderId).remove(); - } -} - -/** - * Update zVM node status - * - * @param data Data returned from HTTP request - */ -function updateZNodeStatus(data) { - var node = data.msg; - var rsp = data.rsp; - - // Get cookie for number processes performed against this node - var actions = $.cookie('xcat_' + node + 'processes'); - // One less process - actions = actions - 1; - $.cookie('xcat_' + node + 'processes', actions, {path: '/xcat', secure:true }); - - if (actions < 1) { - // Hide loader when there are no more processes - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).hide(); - } - - var statBarId = node + 'StatusBar'; - - // Write ajax response to status bar - var prg = writeRsp(rsp, node + ': '); - $('#' + statBarId).find('div').append(prg); -} - -/** - * Update clone status - * - * @param data Data returned from HTTP request - */ -function updateZCloneStatus(data) { - // Get ajax response - var rsp = data.rsp; - var args = data.msg.split(';'); - var cmd = args[0].replace('cmd=', ''); - - // Get provision instance - var inst = args[1].replace('inst=', ''); - // Get output division ID - var out2Id = args[2].replace('out=', ''); - - /** - * (2) Update /etc/hosts - */ - if (cmd == 'nodeadd') { - var node = args[3].replace('node=', ''); - - // If there was an error, do not continue - if (rsp.length) { - $('#' + out2Id).find('img').hide(); - $('#' + out2Id).find('div').append('
                  (Error) Failed to create node definition
                  '); - } else { - $('#' + out2Id).find('div').append('
                  Node definition created for ' + node + '
                  '); - - // If last node definition was created - var tmp = inst.split('/'); - if (tmp[0] == tmp[1]) { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'makehosts', - tgt : '', - args : '', - msg : 'cmd=makehosts;inst=' + inst + ';out=' + out2Id - }, - - success : updateZCloneStatus - }); - } - } - } - - /** - * (3a) Update DNS if source forge xCAT then do makedns - */ - else if ((cmd == 'makehosts') && (builtInXCAT == 0)) { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + out2Id).find('div').append(prg); - - // If there was an error, do not continue - if (rsp.length) { - $('#' + out2Id).find('img').hide(); - $('#' + out2Id).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); - } else { - $('#' + out2Id).find('div').append('
                  /etc/hosts updated
                  '); - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'makedns', - tgt : '', - args : '', - msg : 'cmd=makedns;inst=' + inst + ';out=' + out2Id - }, - - success : updateZCloneStatus - }); - } - } - - /** - * (3b) Update DNS for built in xCAT and clone - * Just clone for sourceforge xCAT - */ - else if (((cmd == 'makehosts') && (builtInXCAT == 1)) || - ((cmd == 'makedns') && (builtInXCAT == 0))) { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + out2Id).find('div').append(prg); - - // If there was an error, do not continue - if (rsp.length) { - $('#' + out2Id).find('img').hide(); - if (builtInXCAT == 1) { - $('#' + out2Id).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); - } else { - $('#' + out2Id).find('div').append('
                  (Error) Failed to makedns
                  '); - } - } - // Get clone tab - var tabId = out2Id.replace('CloneStatusBar', 'CloneTab'); - - // If a node range is given - var tgtNodeRange = $('#' + tabId + ' input[name=tgtNode]').val(); - var tgtNodes = ''; - if (tgtNodeRange.indexOf('-') > -1) { - var tmp = tgtNodeRange.split('-'); - - // Get node base name - var nodeBase = tmp[0].match(/[a-zA-Z]+/); - // Get the starting index - var nodeStart = parseInt(tmp[0].match(/\d+/)); - // Get the ending index - var nodeEnd = parseInt(tmp[1].match(/\d+/)); - for ( var i = nodeStart; i <= nodeEnd; i++) { - // Do not append comma for last node - if (i == nodeEnd) { - tgtNodes += nodeBase + i.toString(); - } else { - tgtNodes += nodeBase + i.toString() + ','; - } - } - } else { - tgtNodes = tgtNodeRange; - } - - // Get other inputs - var srcNode = $('#' + tabId + ' input[name=srcNode]').val(); - hcp = $('#' + tabId + ' input[name=newHcp]').val(); - var group = $('#' + tabId + ' input[name=newGroup]').val(); - var diskPool = $('#' + tabId + ' input[name=diskPool]').val(); - var diskPw = $('#' + tabId + ' input[name=diskPw]').val(); - if (!diskPw) { - diskPw = ''; - } - - // Clone - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'mkvm', - tgt : tgtNodes, - args : srcNode + ';pool=' + diskPool + ';pw=' + diskPw, - msg : 'cmd=mkvm;inst=' + inst + ';out=' + out2Id - }, - error: function(jqXHR, textStatus) { - $('#' + out2Id).find('div').append('
                  (Error) Failed in clone call with ' + textStatus + '
                  '); - }, - success : updateZCloneStatus - }); - } - - /** - * (5) Done - */ - else if (cmd == 'mkvm') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + out2Id).find('div').append(prg); - - // Hide loader - $('#' + out2Id).find('img').hide(); - } -} - -/** - * Get zVM resources - * - * @param data Data from HTTP request - */ -function getZResources(data) { - var tabId = 'zvmResourceTab'; - var info = createInfoBar('Manage storage and networks'); - $('#' + tabId).append(info); - - // Do not continue if there is no output - if (data.rsp.length) { - if (typeof console == "object"){ - console.log("Entering getZResources."); - } - // Push hardware control points into an array - var node, hcp; - var hcpHash = new Object(); - var hostnameHash = new Object(); - for (var i in data.rsp) { - node = data.rsp[i][0]; - hcp = data.rsp[i][1]; - // data will be coming in like "xcat xcat.endicott.ibm.com hosts.hostnames" - // or xcat zhcp.endicott.ibm.com zvm.hcp" - if (data.rsp[i][2]== "zvm.hcp") { - hcpHash[hcp] = 1; - } else { - if (hcp.length) { - hostnameHash[hcp] = node; - } - } - } - - // Create an array for hardware control points - var hcps = new Array(); - for (var key in hcpHash) { - // Get the short host name - //hcp = key.split('.')[0]; //old code - hcp = hostnameHash[key]; - if (typeof console == "object"){ - console.log("getZResources lookup for hostname "+key+" found nodename <"+hcp+">"); - } - if (jQuery.inArray(hcp, hcps) == -1) { - hcps.push(hcp); - } - } - - // Set hardware control point cookie - $.cookie('xcat_hcp', hcps, {path: '/xcat', secure:true }); - - // Delete loader - $('#' + tabId).find('img[src="images/loader.gif"]').remove(); - - // Create accordion panel for disk - var resourcesAccordion = $('
                  '); - var diskSection = $('
                  '); - var diskLnk = $('

                  Disks

                  ').click(function () { - // Do not load panel again if it is already loaded - if ($('#zvmDiskResource').children().length) { - return; - } - else - $('#zvmDiskResource').append(createLoader('')); - - // Resize accordion - $('#zvmResourceAccordion').accordion('resize'); - - // Create a array for hardware control points - var hcps = new Array(); - if ($.cookie('xcat_hcp').indexOf(',') > -1) { - hcps = $.cookie('xcat_hcp').split(','); - } else { - hcps.push($.cookie('xcat_hcp')); - } - - // Query the disk pools for each hcp - var panelId = 'zvmDiskResource'; - var info = $('#' + panelId).find('.ui-state-highlight'); - if (!info.length) { - info = createInfoBar("Querying "+hcps.length+" zhcp(s) for disk pools."); - $('#' + panelId).append(info); - } - zhcpQueryCountForDisks = hcps.length; - - for (var i in hcps) { - var itemcount = +i + 1; - info.append("
                  Querying disk pools from: "+hcps[i]+" ("+itemcount+" of "+hcps.length+")"); - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcps[i], - args : '--diskpoolnames', - msg : hcps[i] - }, - - success : getDiskPool - }); - zhcpQueryCountForDisks--; - } - }); - - // Create accordion panel for zFCP devices - var zfcpSection = $('
                  '); - var zfcpLnk = $('

                  zFCP

                  ').click(function () { - // Do not load panel again if it is already loaded - if ($('#zfcpResource').children().length) - return; - else - $('#zfcpResource').append(createLoader('')); - - // Resize accordion - $('#zvmResourceAccordion').accordion('resize'); - - // Create a array for hardware control points - var hcps = new Array(); - if ($.cookie('xcat_hcp').indexOf(',') > -1) { - hcps = $.cookie('xcat_hcp').split(','); - } else { - hcps.push($.cookie('xcat_hcp')); - - } - - // Query the fcp pools for each hcp - var panelId = 'zfcpResource'; - var info = $('#' + panelId).find('.ui-state-highlight'); - if (!info.length) { - info = createInfoBar("Querying "+hcps.length+" zhcp(s) for fcp pools."); - $('#' + panelId).append(info); - } - zhcpQueryCountForZfcps = hcps.length; - for (var i in hcps) { - // Gather fcp pools from hardware control points - var itemcount = +i + 1; - info.append("
                  Querying fcp pools from: "+hcps[i]+" ("+itemcount+" of "+hcps.length+")"); - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcps[i], - args : '--zfcppoolnames', - msg : hcps[i] - }, - - success : getZfcpPool - }); - zhcpQueryCountForZfcps--; - } - }); - - // Create accordion panel for network - var networkSection = $('
                  '); - var networkLnk = $('

                  Networks

                  ').click(function () { - // Do not load panel again if it is already loaded - if ($('#zvmNetworkResource').children().length) { - return; - } else { - $('#zvmNetworkResource').append(createLoader('')); - } - - // Resize accordion - $('#zvmResourceAccordion').accordion('resize'); - - // Create a array for hardware control points - var hcps = new Array(); - if ($.cookie('xcat_hcp').indexOf(',') > -1) { - hcps = $.cookie('xcat_hcp').split(','); - } else { - hcps.push($.cookie('xcat_hcp')); - - } - // Query the networks for each - var panelId = 'zvmNetworkResource'; - var info = $('#' + panelId).find('.ui-state-highlight'); - if (!info.length) { - info = createInfoBar("Querying "+hcps.length+" zhcp(s) for networks."); - $('#' + panelId).append(info); - } - zhcpQueryCountForNetworks = hcps.length; - for (var i in hcps) { - var itemcount = +i + 1; - info.append("
                  Querying networks from: "+hcps[i]+" ("+itemcount+" of "+hcps.length+")"); - $('#zvmResourceAccordion').accordion('resize'); - // Gather networks from hardware control points - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcps[i], - args : '--getnetworknames', - msg : hcps[i] - }, - - success : getNetwork - }); - zhcpQueryCountForNetworks--; - } - }); - - resourcesAccordion.append(diskLnk, diskSection, zfcpLnk, zfcpSection, networkLnk, networkSection); - - // Append accordion to tab - $('#' + tabId).append(resourcesAccordion); - resourcesAccordion.accordion(); - networkLnk.trigger('click'); - } -} - -/** - * 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 = null; // 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 add processor dialog - * - * @param node Node to add processor to - */ -function openAddProcDialog(node) { - // Create form to add processor - var addProcForm = $('
                  '); - // Create info bar - var info = createInfoBar('Add a temporary processor to this virtual server.'); - addProcForm.append(info); - addProcForm.append('
                  '); - addProcForm.append('
                  '); - - // Create drop down for processor type - var procType = $('
                  '); - procType.append(''); - var typeSelect = $(''); - typeSelect.append('' - + '' - + '' - + '' - ); - procType.append(typeSelect); - addProcForm.append(procType); - - // Generate tooltips - addProcForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add processor - addProcForm.dialog({ - title:'Add processor', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get inputs - var node = $(this).find('input[name=procNode]').val(); - var address = $(this).find('input[name=procAddress]').val(); - var type = $(this).find('select[name=procType]').val(); - - // If inputs are not complete, show warning message - if (!node || !address || !type) { - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this)); - } else { - // Add processor - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--addprocessoractive;' + address + ';' + type, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - var statusId = node + 'StatusBar'; - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).show(); - $('#' + statusId).show(); - - // Close dialog - $(this).dialog( "close" ); - } - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create add disk dialog - * - * @param node Node to add disk to - * @param hcp Hardware control point of node - */ -function openAddDiskDialog(node, hcp) { - // Get list of disk pools - var cookie = $.cookie('xcat_' + hcp + 'diskpools'); - var pools = new Array(); - if (cookie) { - pools = cookie.split(','); - } - - // Create form to add disk - var addDiskForm = $('
                  '); - // Create info bar - var info = createInfoBar('Add a ECKD|3390 or FBA|9336 disk to this virtual server.'); - addDiskForm.append(info); - addDiskForm.append('
                  '); - addDiskForm.append('
                  '); - addDiskForm.append('
                  '); - addDiskForm.append('
                  '); - - // Create drop down for disk pool - var diskPool = $('
                  '); - diskPool.append(''); - var poolSelect = $(''); - for ( var i = 0; i < pools.length; i++) { - if( !pools[i] || 0 === pools[i].length) continue; - poolSelect.append(''); - } - diskPool.append(poolSelect); - addDiskForm.append(diskPool); - - // Create drop down for disk mode - var diskMode = $('
                  '); - diskMode.append(''); - var modeSelect = $(''); - modeSelect.append('' - + '' - + '' - + '' - + '' - + '' - + '' - ); - diskMode.append(modeSelect); - addDiskForm.append(diskMode); - - addDiskForm.append('
                  '); - - // Generate tooltips - addDiskForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add disk - addDiskForm.dialog({ - title:'Add disk', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get inputs - var node = $(this).find('input[name=diskNode]').val(); - var type = $(this).find('select[name=diskType]').val(); - var address = $(this).find('input[name=diskAddress]').val(); - var size = $(this).find('input[name=diskSize]').val(); - var pool = $(this).find('select[name=diskPool]').val(); - var mode = $(this).find('select[name=diskMode]').val(); - var password = $(this).find('input[name=diskPassword]').val(); - - // If inputs are not complete, show warning message - if (!node || !type || !address || !size || !pool || !mode) { - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this)); - } else { - // Add disk - if (type == '3390') { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--add3390;' + pool + ';' + address + ';' + size - + ';' + mode + ';' + password + ';' + password + ';' + password, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - var statusId = node + 'StatusBar'; - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).show(); - $('#' + statusId).show(); - } else if (type == '9336') { - // Default block size for FBA volumes = 512 - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--add9336;' + pool + ';' + address + ';' + size - + ';' + mode + ';' + password + ';' + password + ';' + password, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - var statusId = node + 'StatusBar'; - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).show(); - $('#' + statusId).show(); - } - - // Close dialog - $(this).dialog( "close" ); - } // End of else - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create add zFCP device dialog - * - * @param node Node to add disk to - * @param hcp Hardware control point of node - * @param zvm The z/VM system of node - */ -function openAddZfcpDialog(node, hcp, zvm) { - // Get list of disk pools - var cookie = $.cookie('xcat_' + hcp + 'zfcppools'); - var pools = new Array(); - if (cookie) { - pools = cookie.split(','); - } - - // Create form to add disk - var addZfcpForm = $('
                  '); - // Create info bar - var info = createInfoBar('Add a SCSI|FCP disk to this virtual server.'); - addZfcpForm.append(info); - addZfcpForm.append('
                  '); - addZfcpForm.append('
                  '); - addZfcpForm.append('
                  '); - addZfcpForm.append('
                  '); - - // Create drop down for disk pool - var diskPool = $('
                  '); - diskPool.append(''); - var poolSelect = $(''); - for ( var i = 0; i < pools.length; i++) { - if( !pools[i] || 0 === pools[i].length) continue; - poolSelect.append(''); - } - diskPool.append(poolSelect); - addZfcpForm.append(diskPool); - - // Tag to identify where device will be used - addZfcpForm.append('
                  '); - - // Create advanced link to set advanced zFCP properties - var advancedLnk = $('
                  '); - addZfcpForm.append(advancedLnk); - var advanced = $('
                  ').hide(); - addZfcpForm.append(advanced); - - var portName = $('
                  '); - var unitNo = $('
                  '); - advanced.append(portName, unitNo); - - // Toggle port name and unit number when clicking on advanced link - advancedLnk.click(function() { - advanced.toggle(); - }); - - // Generate tooltips - addZfcpForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add disk - addZfcpForm.dialog({ - title:'Add zFCP device', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get inputs - var node = $(this).find('input[name=diskNode]').val(); - var address = $(this).find('input[name=diskAddress]').val(); - var loaddev = $(this).find('input[name=diskLoaddev]'); - var size = $(this).find('input[name=diskSize]').val(); - var pool = $(this).find('select[name=diskPool]').val(); - var tag = $(this).find('input[name=diskTag]').val(); - var portName = $(this).find('input[name=diskPortName]').val(); - var unitNo = $(this).find('input[name=diskUnitNo]').val(); - - // If inputs are not complete, show warning message - if (!node || !address || !size || !pool) { - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this)); - } else { - if (loaddev.attr('checked')) { - loaddev = 1; - } else { - loaddev = 0; - } - - var args = '--addzfcp||' + pool + '||' + address + '||' + loaddev + '||' + size; - - if (tag && tag != "null") { - args += '||' + tag; - } else { - args += '|| ""'; - } - - if ((portName && portName != "null") && (unitNo && unitNo != "null")) { - args += '||' + portName + '||' + unitNo; - } - - // Add zFCP device - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : args, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - var statusId = node + 'StatusBar'; - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).show(); - $('#' + statusId).show(); - - // Close dialog - $(this).dialog( "close" ); - } - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create dedicate device dialog - * - * @param node Node to dedicate device to - * @param hcp Hardware control point of node - */ -function openDedicateDeviceDialog(node, hcp) { - // Create form to add disk - var dedicateForm = $('
                  '); - // Create info bar - var info = createInfoBar('Add a dedicated device to the configuration'); - dedicateForm.append(info); - - dedicateForm.append('
                  '); - dedicateForm.append('
                  '); - dedicateForm.append('
                  '); - dedicateForm.append('
                  '); - - // Generate tooltips - dedicateForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add dedicated device - dedicateForm.dialog({ - title:'Add dedicated device', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get inputs - var node = $(this).find('input[name=diskNode]').val(); - var vAddress = $(this).find('input[name=virtualAddress]').val(); - var rAddress = $(this).find('input[name=realAddress]').val() - var mode = $(this).find('select[name=mode]').val(); - - // If inputs are not complete, show warning message - if (!node || !vAddress || !rAddress || !mode) { - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this)); - } else { - var args = '--dedicatedevice;' + vAddress + ';' + rAddress + ';' + mode; - - // Add zFCP device - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : args, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - var statusId = node + 'StatusBar'; - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).show(); - $('#' + statusId).show(); - - // Close dialog - $(this).dialog( "close" ); - } - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create add ECKD to system dialog - * - * @param hcp Hardware control point of node - */ -function openAddEckd2SystemDialog(hcp) { - var dialogId = 'zvmAddEckd2System'; - - // Create form to add disk - var addE2SForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - // Create info bar - var info = createInfoBar('Dynamically add an ECKD disk to a running z/VM system.'); - addE2SForm.append(info); - - addE2SForm.append(system); - addE2SForm.append('
                  '); - - // Generate tooltips - addE2SForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add disk - addE2SForm.dialog({ - title:'Add ECKD to system', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 420, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var system = $(this).find('select[name=system]').val(); - var devnum = $(this).find('input[name=devNum]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=devNum]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : "--addeckd;" + devnum, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create add Volume to system dialog - * - * @param hcp Hardware control point of node - */ -function openAddVolume2SystemDialog(hcp) { - var dialogId = 'zvmAddVolume2System'; - - // Create form to add volume - var addV2SForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - // Create info bar - var info = createInfoBar('Permanently add a volume to the z/VM system configuration.'); - addV2SForm.append(info); - - addV2SForm.append(system); - addV2SForm.append('
                  '); - addV2SForm.append('
                  '); - - // Generate tooltips - addV2SForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add volume - addV2SForm.dialog({ - title:'Add volume to system configuration', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 480, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var system = $(this).find('select[name=system]').val(); - var devnum = $(this).find('input[name=devNum]').val(); - var volser = $(this).find('input[name=volser]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=devNum]', 'input[name=volser]' ); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : "--addvolume;" + devnum + ";" + volser, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create remove Volume to system dialog - * - * @param hcp Hardware control point of node - */ -function openRemoveVolumeFromSystemDialog(hcp) { - var dialogId = 'zvmRemoveVolumeFromSystem'; - - // Create form to remove volume - var remVfromSForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - // Create info bar - var info = createInfoBar('Permanently remove a volume from the z/VM system configuration.'); - remVfromSForm.append(info); - - remVfromSForm.append(system); - remVfromSForm.append('
                  '); - remVfromSForm.append('
                  '); - - // Generate tooltips - remVfromSForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to remove volume - remVfromSForm.dialog({ - title:'Remove volume from system configuration', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 580, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var system = $(this).find('select[name=system]').val(); - var devnum = $(this).find('input[name=devNum]').val(); - var volser = $(this).find('input[name=volser]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=devNum]', 'input[name=volser]' ); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : "--removevolume;" + devnum + ";" + volser, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create add page or spool dialog - * - * @param hcp Hardware control point of node - */ -function openAddPageSpoolDialog(hcp) { - var dialogId = 'zvmAddPageSpool'; - - // Create form to add disk - var addPageSpoolForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - // Create info bar - var info = createInfoBar('Add a page or spool volume to be used by zVM.'); - addPageSpoolForm.append(info); - - var diskFS = $('
                  Disk
                  '); - addPageSpoolForm.append(diskFS); - var diskAttr = $('
                  '); - diskFS.append($('
                  ')); - diskFS.append(diskAttr); - - diskAttr.append(system); - diskAttr.append('
                  '); - diskAttr.append('
                  '); - diskAttr.append('
                  '); - - // Generate tooltips - addPageSpoolForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add disk - addPageSpoolForm.dialog({ - title:'Add page or spool', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 500, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var system = $(this).find('select[name=system]').val(); - var volAddr = $(this).find('input[name=volAddr]').val(); - var volLabel = $(this).find('input[name=volLabel]').val(); - var volUse = $(this).find('select[name=volUse]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=volAddr]', 'input[name=volLabel]', 'select[name=volUse]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - var pageSpoolArgs = volAddr + ";" + volLabel + ";" + volUse; - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : system, - args : '--addpagespool;' + pageSpoolArgs, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Open dialog to share disk - * - * @param disks2share Disks selected in table - */ -function openShareDiskDialog(disks2share) { - // Create form to share disk - var dialogId = 'zvmShareDisk'; - var shareDiskForm = $('
                  '); - - var args = disks2share.split(';'); - var tgtHcp = args[0]; - var tgtVol = args[1]; - - if (!tgtVol || tgtVol == "undefined") - tgtVol = ""; - - // Create info bar - var info = createInfoBar('Indicate a full-pack minidisk is to be shared by the users of many real and virtual systems.'); - shareDiskForm.append(info); - - // Set region input based on those selected on table (if any) - var node = $('
                  '); - var volAddr = $('
                  '); - var shareEnable = $('
                  '); - shareDiskForm.append(node, volAddr, shareEnable); - - // Generate tooltips - shareDiskForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to delete disk - shareDiskForm.dialog({ - title:'Share disk', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 500, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get inputs - var node = $(this).find('input[name=node]').val(); - var volAddr = $(this).find('input[name=volAddr]').val(); - var shareEnable = $(this).find('select[name=shareEnable]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('input[name=node]', 'input[name=volAddr]', 'select[name=shareEnable]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // Remove disk from pool - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : "--sharevolume;" + volAddr + ";" + shareEnable, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Create add SCSI 2 system dialog - * - * @param hcp Hardware control point of node - */ -function openAddScsi2SystemDialog(hcp) { - var dialogId = 'zvmAddScsi2System'; - - // Create form to add disk - var addS2SForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - // Create info bar - var info = createInfoBar('Dynamically add an SCSI disk to a running z/VM system as an EDEV.'); - addS2SForm.append(info); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - var devNo = $('
                  '); - var devPathLabel = $(''); - var devPathCount = 1; - //var pathDiv = $('
                  '); - - var devPathDiv = $('
                  '); - var devPathTable = $('
                  '); - var devPathHeader = $(' FCP Device WWPN LUN'); - // Adjust header width - devPathHeader.find('th').css({ - 'width' : '120px' - }); - devPathHeader.find('th').eq(0).css({ - 'width' : '20px' - }); - var devPathBody = $(''); - var devPathFooter = $(''); - - // Create a row - var devPathRow = $(''); - - // Add blank column (remove button replacement) - devPathRow.append(''); - - // Create FCP device number input - var fcpDevNum = $(''); - devPathRow.append(fcpDevNum); - - // Create FCP WWPN input - var fcpWwpn = $(''); - devPathRow.append(fcpWwpn); - - if ($.cookie('xcat_zvms')) { - zvms = $.cookie('xcat_zvms').split(','); - var zvm; - for (var i in zvms) { - if( !zvms[i] || 0 === zvms[i].length) continue; - var args = zvms[i].split(':'); - var zvm = args[0].toLowerCase(); - var iHcp = args[1]; - } - } - - // Create FCP LUN input - var fcpLun = $(''); - devPathRow.append(fcpLun); - - devPathBody.append(devPathRow); - - var addDevPathLink = $('+ Add path'); - addDevPathLink.bind('click', function(event){ - devPathCount = devPathCount + 1; - // Create a row - var devPathRow = $(''); - - // Add remove button - var removeBtn = $('').css({ - "float": "left", - "cursor": "pointer" - }); - var col = $('').append(removeBtn); - removeBtn.bind('click', function(event) { - $(this).parent().parent().remove(); - }); - devPathRow.append(col); - - // Create FCP device number input - var fcpDevNum = $(''); - devPathRow.append(fcpDevNum); - - // Create FCP WWPN input - var fcpWwpn = $(''); - devPathRow.append(fcpWwpn); - - // Create FCP LUN input - var fcpLun = $(''); - devPathRow.append(fcpLun); - - devPathBody.append(devPathRow); - - // Generate tooltips - addS2SForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - }); - devPathFooter.append(addDevPathLink); - devPathTable.append(devPathHeader); - devPathTable.append(devPathBody); - devPathTable.append(devPathFooter); - devPathDiv.append(devPathLabel); - devPathDiv.append(devPathTable); - - var option = $('
                  '); - var persist = $('
                  '); - addS2SForm.append(system, devNo, devPathDiv, option, persist); - - // Generate tooltips - addS2SForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - addS2SForm.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 to add disk - addS2SForm.dialog({ - title:'Add SCSI to running system', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 675, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var system = $(this).find('select[name=system]').val(); - var devNo = $(this).find('input[name=devNo]').val(); - var pathArray = ""; - jQuery('.devPath').each(function(index) { - pathArray += $(this).find('input[name=fcpDevNum]').val() + ','; - pathArray += $(this).find('input[name=fcpWwpn]').val() + ','; - pathArray += $(this).find('input[name=fcpLun]').val() + ';'; - }); - var option = $(this).find('select[name=option]').val(); - var persist = $(this).find('select[name=persist]').val(); - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=fcpDevNum]', 'select[name=option]', 'select[name=persist]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - // Show warning message - if (!ready || !pathArray) { - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : "--addscsi||" + devNo + "||" + pathArray + "||" + option + "||" + persist, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Delete a real SCSI disk - * - * @param hcp Hardware control point of node - */ -function openRemoveScsiDialog(hcp) { - var dialogId = 'zvmRemoveScsiDialog'; - // Create form to add disk - var removeScsiForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - // Create info bar - var info = createInfoBar('Delete a real SCSI disk'); - removeScsiForm.append(info, system); - removeScsiForm.append('
                  '); - removeScsiForm.append('
                  '); - addNicForm.append('
                  '); - - // Create drop down for NIC types - var nicType = $('
                  '); - nicType.append(''); - var nicTypeSelect = $(''); - nicTypeSelect.append('' - + '' - + '' - ); - nicType.append(nicTypeSelect); - addNicForm.append(nicType); - - // Create drop down for network types - var networkType = $('
                  '); - networkType.append(''); - var networkTypeSelect = $(''); - networkTypeSelect.append('' - + '' - + '' - ); - networkType.append(networkTypeSelect); - addNicForm.append(networkType); - var hashtable = getselectedNetworkHash(); - if (!hashtable) { - hashtable = [[]]; - setselectedNetworkHash(hashtable); - - if (typeof console == "object") { - console.log("openAddNicDialog. creating new hash[[]] table." ); - } - } - - // Create drop down for network names - var gLansQdioSelect = $(''); - var gLansHipersSelect = $(''); - var vswitchSelect = $(''); - for ( var i = 0; i < networks.length; i++) { - if( !networks[i] || 0 === networks[i].length) continue; - var network = networks[i].split(' '); - var networkOption = $(''); - if (network[0] == 'VSWITCH') { - vswitchSelect.append(networkOption); - - // Load and save specific vswitch details in global table if not there - network[2] = jQuery.trim(network[2]); // Remove new line x012 from end - if (typeof hashtable[node + '_NIC_' + network[2]] === 'undefined') { - if (typeof console == "object"){ - console.log("Calling getNetworkDetails for switch:<"+network[2]+">"); - } - ajaxrequest = 1; - getNetworkDetails(hcpNode, network[2], node + '_NIC_' + network[2], ''); - } - } else if (network[0] == 'LAN:QDIO') { - gLansQdioSelect.append(networkOption); - } else if (network[0] == 'LAN:HIPERS') { - gLansHipersSelect.append(networkOption); - } - } - - // Hide network name drop downs until the NIC type and network type is selected - // QDIO Guest LAN drop down - var guestLanQdio = $('
                  ').hide(); - guestLanQdio.append(''); - guestLanQdio.append(gLansQdioSelect); - addNicForm.append(guestLanQdio); - - // HIPERS Guest LAN drop down - var guestLanHipers = $('
                  ').hide(); - guestLanHipers.append(''); - guestLanHipers.append(gLansHipersSelect); - addNicForm.append(guestLanHipers); - - // VSWITCH drop down - var vswitch = $('
                  ').hide(); - vswitch.append(''); - vswitch.append(vswitchSelect); - - // VLAN id with Porttype - var vswitchvlan = $('
                  '); - vswitchvlan.append('
                  '); - var vswitchPorttype = $(''); - vswitchvlan.append(vswitchPorttype); - vswitchvlan.append('
                  '); - var vswitchVLANId = $(''); - vswitchvlan.append(vswitchVLANId); - - vswitch.append(vswitchvlan); - vswitchvlan.hide(); - addNicForm.append(vswitch); - - // Show network names on change - networkTypeSelect.change(function(){ - // Remove any warning messages - $(this).parent().parent().find('.ui-state-error').remove(); - var networkType = $(this).val(); - - if (typeof console == "object"){ - console.log("Entering networkTypeSelect.change"); - } - // Get NIC type and network type - var nicType = $(this).parent().parent().find('select[name=nicType]').val(); - var networkType = $(this).val(); - - // Hide network name drop downs - var guestLanQdio = $(this).parent().parent().find('select[name=nicLanQdioName]').parent(); - var guestLanHipers = $(this).parent().parent().find('select[name=nicLanHipersName]').parent(); - var vswitch = $(this).parent().parent().find('select[name=nicVSwitchName]').parent(); - var mynode = $(this).parent().parent().find('input[name=nicNode]').val(); - var showvlan = $(this).parent().parent().find('select[name=vswitchVLANporttype]').parent(); - var hashtable = getselectedNetworkHash(); - guestLanQdio.hide(); - guestLanHipers.hide(); - vswitch.hide(); - - // Show correct network name - if (networkType == 'Guest LAN' && nicType == 'QDIO') { - guestLanQdio.show(); - } else if (networkType == 'Guest LAN' && nicType == 'HiperSockets') { - guestLanHipers.show(); - } else if (networkType == 'Virtual Switch') { - if (nicType == 'QDIO') { - vswitch.show(); - // Show vlan information only if vlan aware - var switchname = $(this).parent().parent().find('select[name=nicVSwitchName]').val(); - var tokens = switchname.split(' '); - var switchkeyid = mynode + '_NIC_' + jQuery.trim(tokens[1]); - if (typeof console == "object"){ - console.log("Checking vswitch index:"+switchkeyid); - } - - // Is this a vlanaware switch, if so show the special fields - if (hashtable[switchkeyid]["vlan_awareness"] == "AWARE") { - showvlan.find('input[name=vswitchvlanid]').val(hashtable[switchkeyid]["vlan_id"]); - showvlan.find('select[name=vswitchVLANporttype]').val(hashtable[switchkeyid]["port_type"]); - showvlan.show(); - } else { - showvlan.hide(); - showvlan.find('input[name=vswitchvlanid]').val('default'); - showvlan.find('select[name=vswitchVLANporttype]').val('default'); - } - } else { - // No such thing as HIPERS VSWITCH - var warn = createWarnBar('The selected choices are not valid.'); - warn.prependTo($(this).parent().parent()); - } - } - }); - - // - // Show network names on change - // - nicTypeSelect.change(function(){ - // Remove any warning messages - $(this).parent().parent().find('.ui-state-error').remove(); - - if (typeof console == "object"){ - console.log("Entering nicTypeSelect.change"); - } - - // Get NIC type and network type - var nicType = $(this).val(); - var networkType = $(this).parent().parent().find('select[name=nicNetworkType]').val(); - var mynode = $(this).parent().parent().find('input[name=nicNode]').val(); - - // Hide network name drop downs - var guestLanQdio = $(this).parent().parent().find('select[name=nicLanQdioName]').parent(); - var guestLanHipers = $(this).parent().parent().find('select[name=nicLanHipersName]').parent(); - var vswitch = $(this).parent().parent().find('select[name=nicVSwitchName]').parent(); - var showvlan = $(this).parent().parent().find('select[name=vswitchVLANporttype]').parent(); - var hashtable = getselectedNetworkHash(); - guestLanQdio.hide(); - guestLanHipers.hide(); - vswitch.hide(); - - // Show correct network name - if (networkType == 'Guest LAN' && nicType == 'QDIO') { - guestLanQdio.show(); - } else if (networkType == 'Guest LAN' && nicType == 'HiperSockets') { - guestLanHipers.show(); - } else if (networkType == 'Virtual Switch') { - if (nicType == 'QDIO') { - vswitch.show(); - var switchname = $(this).parent().parent().find('select[name=nicVSwitchName]').val(); - var tokens = switchname.split(' '); - var switchkeyid = mynode + '_NIC_' + jQuery.trim(tokens[1]); - - if (typeof console == "object"){ - console.log("Entering nictypeselect.change. switchkey:<"+switchkeyid); - } - - // Is this a vlanaware switch, if so show the special fields - if (hashtable[switchkeyid]["vlan_awareness"] == "AWARE") { - showvlan.find('input[name=vswitchvlanid]').val(hashtable[switchkeyid]["vlan_id"]); - showvlan.find('select[name=vswitchVLANporttype]').val(hashtable[switchkeyid]["port_type"]); - showvlan.show(); - } else { - showvlan.hide(); - showvlan.find('input[name=vswitchvlanid]').val('default'); - showvlan.find('select[name=vswitchVLANporttype]').val('default'); - } - - } else { - // No such thing as HIPERS VSWITCH - var warn = createWarnBar('The selected choices are not valid.'); - warn.prependTo($(this).parent().parent()); - } - } - }); - - // - // Determine if vlanid fields need to be shown based on vswitch - // - vswitchSelect.change(function(){ - // Remove any warning messages - $(this).parent().parent().find('.ui-state-error').remove(); - - // Get vlan id division - var showvlan = $(this).parent().parent().find('select[name=vswitchVLANporttype]').parent(); - - // Get selected switch name and break it into tokens - var switchname = $(this).val(); - var tokens = switchname.split(' '); - - // Get the node we are doing this for and index for hash table - var mynode = $(this).parent().parent().find('input[name=nicNode]').val(); - - var tokens = switchname.split(' '); - var switchkeyid = mynode + '_NIC_' + jQuery.trim(tokens[1]); - var hashtable = getselectedNetworkHash(); - - if (typeof console == "object"){ - console.log("Entering vswitchselect.change. switchkey:<"+switchkeyid+">"); - } - // Is this a vlanaware switch, if so show the special fields - if (hashtable[switchkeyid]["vlan_awareness"] == "AWARE") { - $(this).find('').val(hashtable[switchkeyid]["vlan_id"]); - showvlan.find('input[name=vswitchvlanid]').val(hashtable[switchkeyid]["vlan_id"]); - showvlan.find('select[name=vswitchVLANporttype]').val(hashtable[switchkeyid]["port_type"]); - showvlan.show(); - } else { - showvlan.hide(); - showvlan.find('input[name=vswitchvlanid]').val('default'); - showvlan.find('select[name=vswitchVLANporttype]').val('default'); - } - }); - - - // Generate tooltips - addNicForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - - // Open dialog to add NIC - addNicForm.dialog({ - title:'Add NIC', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var ready = true; - var errMsg = ''; - - // Get inputs - var node = $(this).find('input[name=nicNode]').val(); - var nicType = $(this).find('select[name=nicType]').val(); - var networkType = $(this).find('select[name=nicNetworkType]').val(); - var address = $(this).find('input[name=nicAddress]').val(); - - // If inputs are not complete, show warning message - if (!node || !nicType || !networkType || !address) { - errMsg = 'Please provide a value for each missing field.
                  '; - ready = false; - } - - // If a HIPERS VSWITCH is selected, show warning message - if (nicType == 'HiperSockets' && networkType == 'Virtual Switch') { - errMsg += 'The selected choices are not valid.'; - ready = false; - } - - // If there are errors - if (!ready) { - // Show warning message - var warn = createWarnBar(errMsg); - warn.prependTo($(this)); - } else { - // Add guest LAN - if (networkType == 'Guest LAN') { - var temp; - if (nicType == 'QDIO') { - temp = $(this).find('select[name=nicLanQdioName]').val().split(' '); - } else { - temp = $(this).find('select[name=nicLanHipersName]').val().split(' '); - } - - var lanOwner = temp[0]; - var lanName = temp[1]; - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--addnic;' + address + ';' + nicType + ';3', - msg : 'node=' + node + ';addr=' + address + ';lan=' - + lanName + ';owner=' + lanOwner - }, - success : connect2GuestLan - }); - } - - // Add virtual switch - else if (networkType == 'Virtual Switch' && nicType == 'QDIO') { - var temp = $(this).find('select[name=nicVSwitchName]').val().split(' '); - var vswitchName = jQuery.trim(temp[1]); - var switchkeyid = node + '_NIC_' + vswitchName; - var hashtable = getselectedNetworkHash(); - var awareornot = hashtable[switchkeyid]["vlan_awareness"]; - var porttype = $(this).find('select[name=vswitchVLANporttype]').val(); - var lanid = $(this).find('input[name=vswitchvlanid]').val(); - - // Pass additional lanid data in msg for grant use by connect2VSwitch - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--addnic;' + address + ';' + nicType + ';3', - msg : 'node=' + node + ';addr=' + address + ';vsw=' - + vswitchName + ';vlanaware=' + awareornot + ';porttype=' - + porttype + ';lanid=' + lanid - }, - - success : connect2VSwitch - }); - } - - // Increment node process - incrementNodeProcess(node); - - // Show loader - $('#' + node + 'StatusBarLoader').show(); - $('#' + node + 'StatusBar').show(); - - // Close dialog - $(this).dialog( "close" ); - } // End of else - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); - // Make sure ajax is done before putting up dialog - $(document).ajaxStop(function() { - //Remove loading vswitch gif status bar - statBar.hide(); - }); - if (ajaxrequest == 0) { - //Remove loading vswitch gif status bar - statBar.hide(); - } - -} - -/** - * Create add vSwitch/VLAN dialog - * - * @param hcp Hardware control point of node - */ -function openAddVswitchVlanDialog(hcp) { - var dialogId = 'zvmAddVswitchVlan'; - - // Create form to add disk - var addVswitchForm = $('
                  '); - - // Create info bar - var info = createInfoBar('Create a virtual switch or virtual network LAN.'); - - var netFS = $('
                  '); - var netLegend = $('Network'); - netFS.append(netLegend); - - var typeFS = $('
                  ').hide(); - var typeLegend = $('Network'); - typeFS.append(typeLegend); - addVswitchForm.append(info, netFS, typeFS); - - var netAttr = $('
                  '); - netFS.append($('
                  ')); - netFS.append(netAttr); - - var networkTypeDiv = $('
                  '); - var networkType = $('
                  '); - networkTypeDiv.append(networkType) - netAttr.append(networkTypeDiv); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - netAttr.append(system); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - var typeAttr = $('
                  '); - typeFS.append($('
                  ')); - typeFS.append(typeAttr); - - // Create vSwitch parameters - var vswitchOptions = $('
                  ').hide(); - vswitchOptions.append($('
                  ')); - vswitchOptions.append($('
                  ')); - vswitchOptions.append($('
                  ')); - - // Create an advanced link to configure optional network settings - var advancedLnk = $('
                  '); - vswitchOptions.append(advancedLnk); - var advanced = $('
                  ').hide(); - vswitchOptions.append(advanced); - - // Show IP address and hostname inputs on-click - advancedLnk.click(function() { - advanced.toggle(); - }); - - advanced.append($('
                  ')); - advanced.append($('
                  ')); - advanced.append($('
                  ')); - advanced.append($('
                  ')); - advanced.append($('
                  ')); - advanced.append($('
                  ')); - advanced.append($('
                  ')); - advanced.append($('
                  ')); - advanced.append($('
                  ')); - - // Create VLAN parameters - var vlanOptions = $('
                  ').hide(); - vlanOptions.append($('
                  ')); - vlanOptions.append($('
                  ')); - vlanOptions.append($('
                  ')); - vlanOptions.append($('
                  ')); - - typeAttr.append(vswitchOptions, vlanOptions); - - networkType.change(function() { - typeFS.show(); - if ($(this).val() == "vswitch") { - typeFS.find("legend").text("vSwitch"); - vswitchOptions.show(); - vlanOptions.hide(); - } else if ($(this).val() == "vlan") { - typeFS.find("legend").text("VLAN"); - vswitchOptions.hide(); - vlanOptions.show(); - } else { - typeFS.find("legend").text(""); - vswitchOptions.hide(); - vlanOptions.hide(); - typeFS.hide(); - } - }); - - // Generate tooltips - addVswitchForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add vSwitch or VLAN - addVswitchForm.dialog({ - title:'Add vSwitch or VLAN', - modal: true, - close: function() { - $(this).remove(); - }, - width: 750, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var networkType = $(this).find('select[name=networkType]').val(); - if (networkType == "vswitch") { - var networkArgs = "--addvswitch;"; - var system = $(this).find('select[name=system]').val(); - var switchName = $(this).find('input[name=switchName]').val(); - var deviceAddress = $(this).find('input[name=deviceAddress]').val(); - var portName = switchName; - var controllerName = $(this).find('input[name=controllerName]').val(); - var connection = $(this).find('select[name=connection]').val(); - var queueMemoryLimit = $(this).find('input[name=queueMemoryLimit]').val(); - var routingValue = $(this).find('select[name=routingValue]').val(); - var transportType = $(this).find('select[name=transportType]').val(); - var vlanId = $(this).find('input[name=vlanId]').val(); - var portType = $(this).find('select[name=vswitchVLANporttype]').val(); - var updateSysConfig = $(this).find('select[name=updateSysConfig]').val(); - var gvrp = $(this).find('select[name=gvrp]').val(); - var nativeVlanId = $(this).find('input[name=nativeVlanId]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=switchName]', 'input[name=deviceAddress]', 'input[name=controllerName]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - // Show warning message - if (!ready) { - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - if (switchName) - networkArgs += switchName + ";"; - if (deviceAddress) - networkArgs += deviceAddress + ";"; - if (portName) - networkArgs += portName + ";"; - if (controllerName) - networkArgs += controllerName + ";"; - - // Optional parameters - if (connection) - networkArgs += connection + ";"; - if (queueMemoryLimit) - networkArgs += queueMemoryLimit + ";"; - if (routingValue) - networkArgs += routingValue + ";"; - if (transportType) - networkArgs += transportType + ";"; - if (vlanId) - networkArgs += vlanId + ";"; - if (portType) - networkArgs += portType + ";"; - if (updateSysConfig) - networkArgs += updateSysConfig + ";"; - if (gvrp) - networkArgs += gvrp + ";"; - if (nativeVlanId) - networkArgs += nativeVlanId + ";"; - networkArgs = networkArgs.substring(0, networkArgs.length - 1); - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : networkArgs, - msg : dialogId - }, - - success : updateResourceDialog - }); - } else if (networkType == "vlan") { - var networkArgs = "--addvlan;"; - var system = $(this).find('select[name=system]').val(); - var vlanName = $(this).find('input[name=vlanName]').val(); - var vlanOwner = $(this).find('input[name=vlanOwner]').val(); - var vlanType = $(this).find('select[name=vlanType]').val(); - var vlanTransport = $(this).find('select[name=vlanTransport]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=vlanName]', 'input[name=vlanOwner]', 'select[name=vlanType]', 'select[name=vlanTransport]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - // Show warning message - if (!ready) { - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Ethernet Hipersockets are not supported - if (vlanTransport == "2") { - var warn = createWarnBar('Ethernet Hipersockets are not supported'); - warn.prependTo($(this)); - return; - } - - networkArgs += vlanName + ";"; - networkArgs += vlanOwner + ";"; - networkArgs += vlanType + ";"; - networkArgs += vlanTransport; - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : networkArgs, - msg : dialogId - }, - - success : updateResourceDialog - }); - } // End of else if - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Open dialog to delete network - * - * @param node type name for removing network - */ -function openRemoveVswitchVlanDialog(networkList) { - var names = ''; - for (var i in networkList) { - var networkArgs = networkList[i].split(';'); - networkArgs[2] = jQuery.trim(networkArgs[2]); - names += networkArgs[2] + ', '; - } - names = names.substring(0, names.length - 2); // Delete last two characters - - var confirmDialog = $('

                  Are you sure you want to remove ' + names + '?

                  '); - confirmDialog.dialog({ - title: "Confirm", - modal: true, - width: 400, - buttons: { - "Ok": function() { - for (var i in networkList) { - var networkArgs = networkList[i].split(';'); - var node = networkArgs[0]; - var type = networkArgs[1]; - var name = jQuery.trim(networkArgs[2]); - var owner = networkArgs[3]; - - if (type.indexOf("VSWITCH") != -1) { - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : node, - args : '--removevswitch;' + name, - msg : '' - }, - - success: function(data) { - var infoMsg; - - // Create info message - if (jQuery.isArray(data.rsp)) { - infoMsg = ''; - for (var i in data.rsp) { - infoMsg += data.rsp[i] + '
                  '; - } - } else { - infoMsg = data.rsp; - } - - openDialog("info", infoMsg); - } - }); - } else if (type.indexOf("LAN") != -1) { - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : node, - args : '--removevlan;' + name + ';' + owner, - msg : '' - }, - - success: function(data) { - var infoMsg; - - // Create info message - if (jQuery.isArray(data.rsp)) { - infoMsg = ''; - for (var i in data.rsp) { - infoMsg += data.rsp[i] + '
                  '; - } - } else { - infoMsg = data.rsp; - } - - openDialog("info", infoMsg); - } - }); - } - } - $(this).dialog("close"); - }, - "Cancel": function() { - $(this).dialog("close"); - } - } - }); -} - -/** - * Remove processor - * - * @param node Node where processor is attached - * @param address Virtual address of processor - */ -function removeProcessor(node, address) { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--removeprocessor;' + address, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - $('#' + node + 'StatusBarLoader').show(); - $('#' + node + 'StatusBar').show(); -} - -/** - * Remove disk - * - * @param node Node where disk is attached - * @param address Virtual address of disk - */ -function removeDisk(node, address) { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--removedisk;' + address, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - $('#' + node + 'StatusBarLoader').show(); - $('#' + node + 'StatusBar').show(); -} - -/** - * Remove zFCP device - * - * @param node Node where disk is attached - * @param address Virtual address of zFCP device - * @param wwpn World wide port name of zFCP device - * @param lun Logical unit number of zFCP device - */ -function removeZfcp(node, address, wwpn, lun) { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--removezfcp||' + address + '||' + wwpn + '||' + lun, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - $('#' + node + 'StatusBarLoader').show(); - $('#' + node + 'StatusBar').show(); -} - -/** - * Remove NIC - * - * @param node Node where NIC is attached - * @param address Virtual address of NIC - */ -function removeNic(node, nic) { - var args = nic.split('.'); - var address = args[0]; - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--removenic;' + address, - msg : node - }, - - success : updateZNodeStatus - }); - - // Increment node process - incrementNodeProcess(node); - - // Show loader - $('#' + node + 'StatusBarLoader').show(); - $('#' + node + 'StatusBar').show(); -} - -/** - * Set a cookie for the network names of a given node - * - * @param data Data from HTTP request - */ -function setNetworkCookies(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - var node = data.msg; - var networks = data.rsp[0].split(node + ': '); - - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); - $.cookie('xcat_' + node + 'networks', networks, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Get contents of each disk pool - * - * @param data HTTP request data - */ -function getDiskPool(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Invalid") == -1 && data.rsp[0].indexOf("Error") == -1) { - var hcp = data.msg; - var pools = data.rsp[0].split(hcp + ': '); - - // Get contents of each disk pool - for (var i in pools) { - if (pools[i]) { - pools[i] = jQuery.trim(pools[i]); - - // Get used space - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcp, - args : '--diskpool;' + pools[i] + ';used', - msg : 'hcp=' + hcp + ';pool=' + pools[i] + ';stat=used' - }, - - success : loadDiskPoolTable - }); - - // Get free space - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcp, - args : '--diskpool;' + pools[i] + ';free', - msg : 'hcp=' + hcp + ';pool=' + pools[i] + ';stat=free' - }, - - success : loadDiskPoolTable - }); - } // End of if - } // End of for - } else { - // Display any errors in info bar - if (data.rsp.length) { - var panelId = 'zvmDiskResource'; - var info = $('#' + panelId).find('.ui-state-highlight'); - // If there is no info bar, create info bar - if (!info.length) { - info = createInfoBar("Error: "+data.rsp[0]); - $('#' + panelId).append(info); - } else { - info.append("
                  Error: "+data.rsp[0]); - } - } - // Load empty table - loadDiskPoolTable(""); // Must pass something - } -} - -/** - * Get contents of each zFCP pool - * - * @param data HTTP request data - */ -function getZfcpPool(data) { - if (typeof console == "object"){ - console.log("Entering getZfcpPool."); - } - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Invalid") == -1 && data.rsp[0].indexOf("Error") == -1) { - var hcp = data.msg; - var pools = data.rsp[0].split(hcp + ': '); - zhcpQueryCountForZfcps = 0; - // Get contents of each disk pool - for (var i in pools) { - pools[i] = jQuery.trim(pools[i]); - if (pools[i]) { - - // Query used and free space - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcp, - args : '--zfcppool;' + pools[i] + ';all', - msg : 'hcp=' + hcp + ';pool=' + pools[i] - }, - success : loadZfcpPoolTable - }); - } // End of if - } // End of for - } else { - // Display any errors in info bar - if (data.rsp.length) { - var panelId = 'zfcpResource'; - var info = $('#' + panelId).find('.ui-state-highlight'); - // If there is no info bar, create info bar - if (!info.length) { - info = createInfoBar("Error: "+data.rsp[0]); - $('#' + panelId).append(info); - } else { - info.append("
                  Error: "+data.rsp[0]); - } - } - // Load empty table - loadZfcpPoolTable(""); // Must pass something - } -} - -/** - * Get details of each network - * - * @param data HTTP request data - */ -function getNetwork(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Invalid") == -1 && data.rsp[0].indexOf("Error") == -1) { - var hcp = data.msg; - var networks = data.rsp[0].split(hcp + ': '); - if (typeof console == "object"){ - console.log("Entering getNetwork data:<"+networks+">"); - } - - // Loop through each network - for ( var i = 1; i < networks.length; i++) { - if( !networks[i] || 0 === networks[i].length) continue; - var args = networks[i].split(' '); - var type = args[0]; - var name = args[2]; - name = name.replace(/\n/g,''); - - // Get network details - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcp, - args : '--getnetwork;' + name + ';' + type, - msg : 'hcp=' + hcp + ';type=' + type + ';network=' + name - }, - - success : loadNetworkTable - }); - } // End of for - } // End of if - else { - if (data.rsp.length) { - var panelId = 'zvmNetworkResource'; - var info = $('#' + panelId).find('.ui-state-highlight'); - // If there is no info bar, create info bar - if (!info.length) { - info = createInfoBar("Error: "+data.rsp[0]); - $('#' + panelId).append(info); - } else { - info.append("
                  Error: "+data.rsp[0]); - } - } - // Normally load empty table, but not for networks - } -} - -/** - * Load disk pool contents into a table - * - * @param data HTTP request data - */ -function loadDiskPoolTable(data) { - // Remove loader if all hcps queried - var panelId = 'zvmDiskResource'; - if (!zhcpQueryCountForDisks) { - $('#' + panelId).find('img[src="images/loader.gif"]').remove(); - } - - var hcp2zvm = new Object(); - var args, hcp, pool, stat, tmp; - if (data && typeof data.rsp != "undefined") { - // Do not continue if the call failed - if (!data.rsp.length && data.rsp[0].indexOf("Failed") > 0 && data.rsp[0].indexOf("Error") > 0) { - return; - } - - // Obtain mapping for zHCP to zVM system - hcp2zvm = getHcpZvmHash(); - - args = data.msg.split(';'); - hcp = args[0].replace('hcp=', ''); - pool = args[1].replace('pool=', ''); - stat = jQuery.trim(args[2].replace('stat=', '')); - tmp = data.rsp[0].split(hcp + ': '); - } else { - // Provide empty values so the table will be generated - hcp = ''; - pool = ''; - stat = ''; - tmp = new Array(); - } - - // Resource tab ID - var info = $('#' + panelId).find('.ui-state-highlight'); - // If there is no info bar - if (!info.length) { - // Create info bar - info = createInfoBar('Below are disks that are defined in the EXTENT CONTROL file.'); - $('#' + panelId).append(info); - } - - // Get datatable - var tableId = 'zDiskDataTable'; - var dTable = getDiskDataTable(); - if (!dTable) { - // Create a datatable - var table = new DataTable(tableId); - // Resource headers: volume ID, device type, start address, and size - table.init( [ '', 'z/VM', 'Pool', 'Status', 'Volume', 'Device type', 'Starting address', 'Size' ]); - - // Append datatable to panel - $('#' + panelId).append(table.object()); - - // Turn into datatable - dTable = $('#' + tableId).dataTable({ - 'iDisplayLength': 50, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - setDiskDataTable(dTable); - } - - // Skip index 0 and 1 because it contains nothing - for (var i = 2; i < tmp.length; i++) { - tmp[i] = jQuery.trim(tmp[i]); - var diskAttrs = tmp[i].split(' '); - var key = hcp2zvm[hcp] + "-" + pool + "-" + diskAttrs[0]; - var type = diskAttrs[1]; - - // Calculate disk size - var size; - if (type.indexOf('3390') != -1) { - size = convertCylinders2Gb(parseInt(diskAttrs[3])); - } else if (type.indexOf('9336') != -1) { - size = convertBlocks2Gb(parseInt(diskAttrs[3])) - } else { - size = 0; - } - dTable.fnAddData( [ '', hcp2zvm[hcp], pool, stat, diskAttrs[0], type, diskAttrs[2], diskAttrs[3] + " (" + size + "G)" ]); - } - - // Create actions menu - if (!$('#zvmDiskResourceActions').length) { - // Empty filter area - $('#' + tableId + '_length').empty(); - - // Add disk to pool - var addLnk = $('Add'); - addLnk.bind('click', function(event){ - openAddDisk2PoolDialog(); - }); - - // Delete disk from pool - var removeLnk = $('Remove'); - removeLnk.bind('click', function(event){ - var disks = getNodesChecked(tableId); - openRemoveDiskFromPoolDialog(disks); - }); - - // Refresh table - var refreshLnk = $('Refresh'); - refreshLnk.bind('click', function(event){ - $('#zvmDiskResource').empty().append(createLoader('')); - setDiskDataTable(''); - - // Create a array for hardware control points - var hcps = new Array(); - if ($.cookie('xcat_hcp').indexOf(',') > -1) - hcps = $.cookie('xcat_hcp').split(','); - else - hcps.push($.cookie('xcat_hcp')); - - zhcpQueryCountForDisks = hcps.length; - // Query the disk pools for each - for (var i in hcps) { - if( !hcps[i] || 0 === hcps[i].length) continue; - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcps[i], - args : '--diskpoolnames', - msg : hcps[i] - }, - - success : getDiskPool - }); - zhcpQueryCountForDisks--; - } - }); - - // Add ECKD to system - var addEckdLnk = $('Add ECKD'); - addEckdLnk.bind('click', function(event){ - openAddEckd2SystemDialog(hcp); - }); - - // Add Page or Spool - var addPageSpoolLnk = $('Add page/spool') - addPageSpoolLnk.bind('click', function(event){ - openAddPageSpoolDialog(hcp); - }); - - // Add EDEV to system - var addEdevLnk = $('Add EDEV'); - addEdevLnk.bind('click', function(event){ - openAddScsi2SystemDialog(hcp); - }); - - // Remove EDEV - var removeEdevLnk = $('Remove EDEV'); - removeEdevLnk.bind('click', function(event){ - openRemoveScsiDialog(hcp); - }); - - // Indicate disk is to be shared with various users - var shareLnk = $('Share disk'); - shareLnk.bind('click', function(event){ - var disks = getNodesChecked(tableId); - openShareDiskDialog(disks); - }); - - // Add Volume to system - var addVolumeLnk = $('Add volume to system'); - addVolumeLnk.bind('click', function(event){ - openAddVolume2SystemDialog(hcp); - }); - - // Remove Volume from system - var removeVolumeLnk = $('Remove volume from system'); - removeVolumeLnk.bind('click', function(event){ - openRemoveVolumeFromSystemDialog(hcp); - }); - - // Advanced menu - var advancedLnk = 'Advanced'; - var advancedMenu = createMenu([addEckdLnk, addPageSpoolLnk, addEdevLnk, removeEdevLnk, addVolumeLnk, removeVolumeLnk, shareLnk]); - - // Create action bar - var actionBar = $('
                  ').css("width", "450px"); - - // Create an action menu - var actionsMenu = createMenu([refreshLnk, addLnk, removeLnk, [advancedLnk, advancedMenu]]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + tableId + '_length').prepend(menuDiv); - $('#' + tableId + '_length').css({ - 'padding': '0px', - 'width': '500px' - }); - $('#' + tableId + '_filter').css('padding', '10px'); - menuDiv.append(actionBar); - } - - // Resize accordion - $('#zvmResourceAccordion').accordion('resize'); -} - -/** - * Load zFCP pool contents into a table - * - * @param data HTTP request data - */ -function loadZfcpPoolTable(data) { - if (typeof console == "object"){ - console.log("Entering loadZfcpPoolTable."); - } - // Delete loader if last one - var panelId = 'zfcpResource'; - if (zhcpQueryCountForZfcps <= 0) { - $('#' + panelId).find('img[src="images/loader.gif"]').remove(); - } - - var hcp2zvm = new Object(); - var args, hcp, pool, tmp; - - // Resource tab ID - var info = $('#' + panelId).find('.ui-state-highlight'); - - // Is there any data passed? Process if some - if (typeof data.rsp != "undefined") { - // Do not continue if no data to add - if (!data.rsp.length) { - if (typeof console == "object"){ - console.log("data.rsp.length is 0."); - } - // If there is no info bar, create info bar - var msgError = '
                  Unexpected, no data returned on the lsvm --zfcppool call.'; - if (!info.length) { - info = createInfoBar(msgError); - $('#' + panelId).append(info); - } else { - info.append(msgError); - } - return; - } - if (data.rsp[0].indexOf("Failed") > 0 || data.rsp[0].indexOf("Error") > 0) { - if (typeof console == "object"){ - console.log("Failed on lsvm call for --zfcppool"); - } - var msgError = '
                  Error: Error on call to check zfcp pools: '+ data.rsp[0]; - // If there is no info bar, create info bar - if (!info.length) { - info = createInfoBar(msgError); - $('#' + panelId).append(info); - } else { - info.append(msgError); - } - return; - } - - // Obtain mapping for zHCP to zVM system - hcp2zvm = getHcpZvmHash(); - - args = data.msg.split(';'); - hcp = args[0].replace('hcp=', ''); - pool = args[1].replace('pool=', ''); - tmp = data.rsp[0].split(hcp + ': '); - } else { - // Provide empty values so the table will be generated - if (typeof console == "object"){ - console.log("Creating empty zfcp pool table."); - } - hcp = ''; - pool = '' - tmp = new Array(); - } - - // If there is no info bar, create info bar - if (!info.length) { - info = createInfoBar('Below are devices that are defined internally in the zFCP pools.'); - $('#' + panelId).append(info); - } - - // Get datatable - var tableId = 'zFcpDataTable'; - var dTable = getZfcpDataTable(); - if (!dTable) { - // Create a datatable - var table = new DataTable(tableId); - // Resource headers: status, WWPN, LUN, size, owner, channel, tag - table.init( [ '', 'z/VM', 'Pool', 'Status', 'Port name', 'Unit number', 'Size', 'Range', 'Owner', 'Channel', 'Tag' ]); - - // Append datatable to panel - $('#' + panelId).append(table.object()); - - // Turn into datatable - dTable = $('#' + tableId).dataTable({ - 'iDisplayLength': 50, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - setZfcpDataTable(dTable); - } - if ((typeof data.rsp != "undefined") && (data.rsp.length > 0)) { - // Skip index 0 and 1 because it contains nothing - var key = ""; - for (var i = 2; i < tmp.length; i++) { - tmp[i] = jQuery.trim(tmp[i]); - var diskAttrs = tmp[i].split(','); - diskAttrs[0] = diskAttrs[0].toLowerCase(); - // Key contains row data to be returned when the checkbox is selected - var key = hcp2zvm[hcp] + '-' + pool + '-' + diskAttrs[2] + '-' + diskAttrs[1]; - dTable.fnAddData( [ '', hcp2zvm[hcp], pool, diskAttrs[0], diskAttrs[1], diskAttrs[2], diskAttrs[3], diskAttrs[4], diskAttrs[5], diskAttrs[6], diskAttrs[7] ]); - } - } - // Create actions menu - if (!$('#zFcpResourceActions').length) { - // Empty filter area - $('#' + tableId + '_length').empty(); - - // Add disk to pool - var addLnk = $('Add'); - addLnk.bind('click', function(event){ - openAddZfcp2PoolDialog(); - }); - - // Delete disk from pool - var removeLnk = $('Remove'); - removeLnk.bind('click', function(event){ - if (typeof console == "object"){ - console.log("Remove button clicked for tableId:"+tableId); - } - var disks = getNodesChecked(tableId); - openRemoveZfcpFromPoolDialog(disks); - }); - - // Refresh table - var refreshLnk = $('Refresh'); - refreshLnk.bind('click', function(event){ - $('#zfcpResource').empty().append(createLoader('')); - setZfcpDataTable(''); - - // Create a array for hardware control points - var hcps = new Array(); - if ($.cookie('xcat_hcp').indexOf(',') > -1) - hcps = $.cookie('xcat_hcp').split(','); - else - hcps.push($.cookie('xcat_hcp')); - - // Query the disk pools for each - zhcpQueryCountForZfcps = hcps.length; - for (var i in hcps) { - if( !hcps[i] || 0 === hcps[i].length) continue; - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcps[i], - args : '--zfcppoolnames', - msg : hcps[i] - }, - - success : getZfcpPool - }); - zhcpQueryCountForZfcps--; - } - }); - // Create action bar - var actionBar = $('
                  ').css("width", "450px"); - - // Create an action menu - var actionsMenu = createMenu([addLnk, removeLnk, refreshLnk]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + tableId + '_length').prepend(menuDiv); - $('#' + tableId + '_length').css({ - 'padding': '0px', - 'width': '500px' - }); - $('#' + tableId + '_filter').css('padding', '10px'); - menuDiv.append(actionBar); - } - - // Resize accordion - $('#zvmResourceAccordion').accordion('resize'); -} - -/** - * Open dialog to remove disk from pool - * - * @param disks2remove Disks selected in table - */ -function openRemoveDiskFromPoolDialog(disks2remove) { - // Create form to delete disk from pool - var dialogId = 'zvmDeleteDiskFromPool'; - var deleteDiskForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - var disks = new Array(); - if (disks2remove.indexOf(',') > -1) - disks = disks2remove.split(','); - else - disks.push(disks2remove); - - // Pick the last zHCP and pool it finds - var args, tgtHcp = "", tgtPool = "", tgtVol = ""; - for (var i in disks) { - if( !disks[i] || 0 === disks[i].length) continue; - args = disks[i].split('-'); - tgtHcp = args[0]; - tgtPool = args[1]; - tgtVol += args[2] + ','; - } - - // Strip out last comma - tgtVol = tgtVol.slice(0, -1); - - // Create info bar - var info = createInfoBar('Remove a disk from a disk pool defined in the EXTENT CONTROL.'); - deleteDiskForm.append(info); - var action = $('
                  '); - var actionSelect = $(''); - action.append(actionSelect); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - // Set region input based on those selected on table (if any) - var region = $('
                  '); - var group = $('
                  '); - deleteDiskForm.append(action, system, region, group); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - systemSelect.val(tgtHcp); - - actionSelect.change(function() { - if ($(this).val() == '1' || $(this).val() == '3') { - region.show(); - group.hide(); - } else if ($(this).val() == '2') { - region.show(); - group.show(); - } else if ($(this).val() == '7') { - region.val('FOOBAR'); - region.hide(); - group.show(); - } - }); - - // Generate tooltips - deleteDiskForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to delete disk - deleteDiskForm.dialog({ - title:'Delete disk from pool', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 500, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get inputs - var action = $(this).find('select[name=action]').val(); - var system = $(this).find('select[name=system]').val(); - var region = $(this).find('input[name=region]').val(); - var group = $(this).find('input[name=group]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'select[name=action]', 'input[name=region]', 'input[name=group]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - var args; - if (action == '2' || action == '7') - args = region + ';' + group; - else - args = region; - - // Remove disk from pool - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : '--removediskfrompool;' + action + ';' + args, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Open dialog to add disk to pool - */ -function openAddDisk2PoolDialog() { - // Create form to add disk to pool - var dialogId = 'zvmAddDisk2Pool'; - var addDiskForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - // Create info bar - var info = createInfoBar('Add a disk to a disk pool defined in the EXTENT CONTROL. The disk has to already be attached to SYSTEM.'); - addDiskForm.append(info); - var action = $('
                  '); - var actionSelect = $(''); - action.append(actionSelect); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - var volume = $('
                  '); - var group = $('
                  '); - addDiskForm.append(action, system, volume, group); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - // Generate tooltips - addDiskForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add disk - addDiskForm.dialog({ - title:'Add disk to pool', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 500, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get inputs - var action = $(this).find('select[name=action]').val(); - var system = $(this).find('select[name=system]').val(); - var volume = $(this).find('input[name=volume]').val(); - var group = $(this).find('input[name=group]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'select[name=action]', 'input[name=volume]', 'input[name=group]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - var args; - if (action == '4') - args = volume + ';' + volume + ';' + group; - else - args = volume + ';' + group; - - // Add disk to pool - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : '--adddisk2pool;' + action + ';' + args, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Open dialog to remove zFCP from pool - * - * @param devices2remove Comman separated devices selected in table - */ -function openRemoveZfcpFromPoolDialog(devices2remove) { - // Create form to delete device from pool - var dialogId = 'zvmDeleteZfcpFromPool'; - var deleteDiskForm = $('
                  '); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - // Verify disks are in the same zFCP pool - var devices = devices2remove.split(','); - if (typeof console == "object"){ - console.log("Entering openRemoveZfcpFromPoolDialog. Device to remove:<"+devices2remove+">"); - } - var tmp, tgtPool, tgtHcp; - var tgtPort = ""; - var tgtUnitNo = ""; - for (var i in devices) { - if( !devices[i] || 0 === devices[i].length) continue; - tmp = devices[i].split('-'); - - if (tgtPool && tmp[1] != tgtPool) { - openDialog("warn", "Please select devices in the same zFCP"); - return; - } else { - tgtPool = tmp[1]; - } - - tgtHcp = tmp[0]; // Assume it is just one zHCP. Otherwise, this cannot be done on multiple zHCPs. - tgtUnitNo += tmp[2] + ","; - tgtPort = tmp[3]; - } - - // Strip out last comma - tgtUnitNo = tgtUnitNo.slice(0, -1); - - // Create info bar - var info = createInfoBar('Remove a zFCP device that is defined in a zFCP pool.'); - deleteDiskForm.append(info); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - var pool = $('
                  '); - var unitNo = $('
                  '); - var portName = $('
                  '); - deleteDiskForm.append(system, pool, unitNo, portName); - - // Append options for hardware control points - //systemSelect.append($('')); - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - systemSelect.val(tgtHcp); - - // Generate tooltips - deleteDiskForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to delete device - deleteDiskForm.dialog({ - title:'Delete device from pool', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 500, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var system = $(this).find('select[name=system]').val(); - var pool = $(this).find('input[name=zfcpPool]').val(); - var unitNo = $(this).find('input[name=zfcpUnitNo]').val(); - var portName = $(this).find('input[name=zfcpPortName]').val(); - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=zfcpPool]', 'input[name=zfcpUnitNo]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - var args = '--removezfcpfrompool;' + pool + ';' + unitNo; - if (portName) { - args += ';' + portName; - } - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : system, - args : args, - msg : dialogId - }, - - success : function(data) { - updateResourceDialog(data); - } - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Open dialog to add zFCP to pool - */ -function openAddZfcp2PoolDialog() { - // Create form to add disk to pool - var dialogId = 'zvmAddDisk2Pool'; - var addDiskForm = $('
                  '); - var info = createInfoBar('Add a device to a zFCP pool defined in xCAT.'); - addDiskForm.append(info); - - // Obtain mapping for zHCP to zVM system - var hcp2zvm = new Object(); - hcp2zvm = getHcpZvmHash(); - - var system = $('
                  '); - var systemSelect = $(''); - system.append(systemSelect); - - var pool = $('
                  '); - var status = $('
                  '); - var portName = $('
                  '); - var unitNo = $('
                  '); - var size = $('
                  '); - var range = $('
                  '); - var owner = $('
                  '); - addDiskForm.append(system, pool, status, portName, unitNo, size, range, owner); - - // Create a array for hardware control points - //systemSelect.append($('')); - // Append options for hardware control points - for (var hcp in hcp2zvm) { - systemSelect.append($('')); - } - - // Generate tooltips - addDiskForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add disk - addDiskForm.dialog({ - title:'Add device to pool', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 500, - buttons: { - "Ok": function(){ - // Delete any warning messages - $(this).find('.ui-state-error').remove(); - - var tgtSystem = $(this).find('select[name=system]').val(); - var tgtPool = $(this).find('input[name=zfcpPool]').val(); - var tgtStatus = $(this).find('select[name=zfcpStatus]').val(); - var tgtPortName = $(this).find('input[name=zfcpPortName]').val(); - var tgtUnitNo = $(this).find('input[name=zfcpUnitNo]').val(); - var tgtSize = $(this).find('input[name=zfcpSize]').val(); - var tgtRange = $(this).find('input[name=zfcpRange]').val(); - - // Device owner is optional - var tgtOwner = ""; - if ($(this).find('input[name=zfcpOwner]').val()) { - tgtOwner = $(this).find('input[name=zfcpOwner]').val(); - } - - // If inputs are not complete, show warning message - var ready = true; - var args = new Array('select[name=system]', 'input[name=zfcpPool]', 'select[name=zfcpStatus]', 'input[name=zfcpPortName]', 'input[name=zfcpUnitNo]'); - for (var i in args) { - if (!$(this).find(args[i]).val()) { - $(this).find(args[i]).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); - } - } - - if (!ready) { - // Show warning message - var warn = createWarnBar('Please provide a value for each required field.'); - warn.prependTo($(this)); - return; - } - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // zFCP range and owner are optional - var args = '--addzfcp2pool||' + tgtPool + '||' + tgtStatus + '||"' + tgtPortName + '"||' + tgtUnitNo + '||' + tgtSize; - if (tgtRange) { - args += '||' + tgtRange; - } if (tgtOwner) { - args += '||' + tgtOwner; - } - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chhypervisor', - tgt : tgtSystem, - args : args, - msg : dialogId - }, - - success : updateResourceDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Update resource dialog - * - * @param data HTTP request data - */ -function updateResourceDialog(data) { - var dialogId = data.msg; - var infoMsg; - - // Create info message - if (jQuery.isArray(data.rsp)) { - infoMsg = ''; - for (var i in data.rsp) { - infoMsg += data.rsp[i] + '
                  '; - } - } else { - infoMsg = data.rsp; - } - - // Create info bar with close button - var infoBar = $('
                  ').css('margin', '5px 0px'); - var icon = $('').css({ - 'display': 'inline-block', - 'margin': '10px 5px' - }); - - // Create close button to close info bar - var close = $('').css({ - 'display': 'inline-block', - 'float': 'right' - }).click(function() { - $(this).parent().remove(); - }); - - var msg = $('
                  ' + infoMsg + '
                  ').css({ - 'display': 'inline-block', - 'width': '90%' - }); - - infoBar.append(icon, msg, close); - infoBar.prependTo($('#' + dialogId)); -} - -/** - * Select all checkboxes in the datatable - * - * @param event Event on element - * @param obj Object triggering event - */ -function selectAllDisk(event, obj) { - // This will ascend from - var tableObj = obj.parents('.datatable'); - var status = obj.attr('checked'); - tableObj.find(' :checkbox').attr('checked', status); - - // Handle datatable scroll - tableObj = obj.parents('.dataTables_scroll'); - if (tableObj.length) { - tableObj.find(' :checkbox').attr('checked', status); - } - - event.stopPropagation(); -} - -/** - * Load network details into a table - * - * @param data HTTP request data - */ -function loadNetworkTable(data) { - // Remove loader if last one - var panelId = 'zvmNetworkResource'; - if (!zhcpQueryCountForNetworks) { - $('#' + panelId).find('img[src="images/loader.gif"]').remove(); - } - - // Get zVM host names - if (!$.cookie('xcat_zvms')) { - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - async: false, - data : { - cmd : 'webportal', - tgt : '', - args : 'lszvm', - msg : '' - }, - - success : function(data) { - setzVMCookies(data); - } - }); - } - - var zvms = $.cookie('xcat_zvms').split(','); - var hcp2zvm = new Object(); - var args, zvm, iHcp, tmp; - for (var i in zvms) { - if( !zvms[i] || 0 === zvms[i].length) continue; - args = zvms[i].split(':'); - zvm = args[0].toLowerCase(); - - if (args[1].indexOf('.') != -1) { - tmp = args[1].split('.'); - iHcp = tmp[0]; - } else { - iHcp = args[1]; - } - - hcp2zvm[iHcp] = zvm; - } - - var args = data.msg.split(';'); - var hcp = args[0].replace('hcp=', ''); - var type = args[1].replace('type=', ''); - var name = jQuery.trim(args[2].replace('network=', '')); - tmp = data.rsp[0].split(hcp + ': '); - - // Resource tab ID - var info = $('#' + panelId).find('.ui-state-highlight'); - // If there is no info bar - if (!info.length) { - // Create info bar - info = createInfoBar('Below are LANs/VSWITCHes available to use.'); - $('#' + panelId).append(info); - } - - // Get datatable - var dTable = getNetworkDataTable(); - if (!dTable) { - // Create table - var tableId = 'zNetworkDataTable'; - var table = new DataTable(tableId); - table.init( [ '', 'z/VM', 'Type', 'Name', 'Layer', 'Owner', 'Controller', 'Details' ]); - - // Append datatable to tab - $('#' + panelId).append(table.object()); - - // Turn into datatable - dTable = $('#' + tableId).dataTable({ - 'iDisplayLength': 50, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - setNetworkDataTable(dTable); - - // Set the column width - var cols = table.object().find('thead tr th'); - cols.eq(0).css('width', '20px'); // HCP column - cols.eq(1).css('width', '20px'); // Type column - cols.eq(2).css('width', '20px'); // Name column - cols.eq(3).css({'width': '600px'}); // Details column - } - - // Skip index 0 because it contains nothing - var details = '
                  ';
                  -    for ( var i = 1; i < tmp.length; i++) {
                  -        details += tmp[i];
                  -    }
                  -    details += '
                  '; - - // Determine the OSI layer - var layer = "3"; - if (details.indexOf("ETHERNET") != -1) { - layer = "2"; - } - - // Find the vSwitch/VLAN owner - var regex = /(LAN|VSWITCH) (.*?)(?:\s|$)/g; - var owner = ""; - var match = ""; - if (type == "VSWITCH") { - owner = "SYSTEM"; - } else { - owner = regex.exec(details)[2]; - } - - // Find the vSwitch controller - regex = /(?:^|\s)Controller: (.*?)(?:\s|$)/g; - var controllers = ""; - match = ""; - while (match = regex.exec(details)) { - controllers += match[1] + ","; - } - controllers = controllers.substring(0, controllers.length - 1); // Delete last two characters - - dTable.fnAddData(['', '
                  ' + hcp2zvm[hcp] + '
                  ', '
                  ' + type + '
                  ', '
                  ' + name + '
                  ', '
                  ' + layer + '
                  ', '
                  ' + owner + '
                  ', '
                  ' + controllers + '
                  ', details]); - - // Create actions menu - if (!$('#networkResourceActions').length) { - // Empty filter area - $('#' + tableId + '_length').empty(); - - // Add Vswitch/Vlan - var addLnk = $('Add'); - addLnk.bind('click', function(event){ - openAddVswitchVlanDialog(); - }); - - // Remove Vswitch/Vlan - var removeLnk = $('Remove'); - removeLnk.bind('click', function(event){ - var networkList = getNodesChecked(tableId).split(','); - if (networkList) { - openRemoveVswitchVlanDialog(networkList); - } - }); - - // Refresh table - var refreshLnk = $('Refresh'); - refreshLnk.bind('click', function(event){ - $('#zvmNetworkResource').empty().append(createLoader('')); - setNetworkDataTable(''); - - // Create a array for hardware control points - var hcps = new Array(); - if ($.cookie('xcat_hcp').indexOf(',') > -1) - hcps = $.cookie('xcat_hcp').split(','); - else - hcps.push($.cookie('xcat_hcp')); - - // Query networks - zhcpQueryCountForNetworks = hcps.length; - for (var i in hcps) { - if( !hcps[i] || 0 === hcps[i].length) continue; - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : hcps[i], - args : '--getnetworknames', - msg : hcps[i] - }, - - success : getNetwork - }); - zhcpQueryCountForNetworks--; - } - }); - - // Create action bar - var actionBar = $('
                  ').css("width", "450px"); - - // Create an action menu - var actionsMenu = createMenu([addLnk, removeLnk, refreshLnk]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + tableId + '_length').prepend(menuDiv); - $('#' + tableId + '_length').css({ - 'padding': '0px', - 'width': '500px' - }); - $('#' + tableId + '_filter').css('padding', '10px'); - menuDiv.append(actionBar); - } - - // Resize accordion - $('#zvmResourceAccordion').accordion('resize'); -} - -/** - * Connect a NIC to a Guest LAN - * - * @param data Data from HTTP request - */ -function connect2GuestLan(data) { - var rsp = data.rsp; - var args = data.msg.split(';'); - var node = args[0].replace('node=', ''); - var address = args[1].replace('addr=', ''); - var lanName = args[2].replace('lan=', ''); - var lanOwner = args[3].replace('owner=', ''); - - // Write ajax response to status bar - var prg = writeRsp(rsp, node + ': '); - $('#' + node + 'StatusBar').find('div').append(prg); - - // Continue if no errors found - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - // Connect NIC to Guest LAN - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--connectnic2guestlan;' + address + ';' + lanName + ';' - + lanOwner, - msg : node - }, - - success : updateZNodeStatus - }); - } else { - // Hide loader when error - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).hide(); - } -} - -/** - * Connect a NIC to a VSwitch - * - * @param data Data from HTTP request - */ -function connect2VSwitch(data) { - var rsp = data.rsp; - var args = data.msg.split(';'); - var node = args[0].replace('node=', ''); - var address = args[1].replace('addr=', ''); - var vswitchName = args[2].replace('vsw=', ''); - var vswitchAware = args[3].replace('vlanaware=', ''); - var vswitchPortType = args[4].replace('porttype=', ''); - var vswitchLanId = args[5].replace('lanid=', ''); - - // Set variables to empty string if notaware or they contain "default" - if (vswitchAware.toLowerCase() == 'notaware' ) { - vswitchPortType = ''; - vswitchLanId = ''; - } else { - if (vswitchPortType.toLowerCase() == 'default' ) { - vswitchPortType = ''; - } - if (vswitchLanId.toLowerCase() == 'default' ) { - vswitchLanId = ''; - } - } - - // Write ajax response to status bar - var prg = writeRsp(rsp, node + ': '); - $('#' + node + 'StatusBar').find('div').append(prg); - - // Continue if no errors found - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - // Connect NIC to VSwitch - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chvm', - tgt : node, - args : '--connectnic2vswitch;' + address + ';' + vswitchName + ';' - + vswitchPortType + ';' + vswitchLanId, - msg : node - }, - - success : updateZNodeStatus - }); - } else { - // Hide loader when error - var statusBarLoaderId = node + 'StatusBarLoader'; - $('#' + statusBarLoaderId).hide(); - } -} - -/** - * Create provision existing node division - * - * @param inst Provision tab instance - * @return Provision existing node division - */ -function createZProvisionExisting(inst) { - // Create provision existing and hide it - var provExisting = $('
                  ').hide(); - - var vmFS = $('
                  '); - var vmLegend = $('Virtual Machine'); - vmFS.append(vmLegend); - provExisting.append(vmFS); - - var vmAttr = $('
                  '); - vmFS.append($('
                  ')); - vmFS.append(vmAttr); - - var osFS = $('
                  '); - var osLegend = $('Operating System'); - osFS.append(osLegend); - provExisting.append(osFS); - - var osAttr = $('
                  '); - osFS.append($('
                  ')); - osFS.append(osAttr); - - // Create group input - var group = $('
                  '); - var groupLabel = $(''); - group.append(groupLabel); - - // Turn on auto complete for group - var groupNames = $.cookie('xcat_groups'); - if (groupNames) { - // Split group names into an array - var tmp = groupNames.split(','); - - // Create drop down for groups - var groupSelect = $(''); - groupSelect.append(''); - for (var i in tmp) { - if( !tmp[i] || 0 === tmp[i].length) continue; - // Add group into drop down - var opt = $(''); - groupSelect.append(opt); - } - group.append(groupSelect); - - // Create node datatable - groupSelect.change(function(){ - // Get group selected - var thisGroup = $(this).val(); - // If a valid group is selected - if (thisGroup) { - createNodesDatatable(thisGroup, 'zNodesDatatableDIV' + inst); - } - }); - } else { - // If no groups are cookied - var groupInput = $(''); - group.append(groupInput); - } - vmAttr.append(group); - - // Create node input - var node = $('
                  '); - var nodeLabel = $(''); - var nodeDatatable = $('

                  Select a group to view its nodes

                  '); - node.append(nodeLabel); - node.append(nodeDatatable); - vmAttr.append(node); - - // Create operating system image input - var os = $('
                  '); - var osLabel = $(''); - var osSelect = $(''); - osSelect.append($('')); - - var imageNames = $.cookie('xcat_imagenames').split(','); - if (imageNames) { - imageNames.sort(); - for (var i in imageNames) { - if( !imageNames[i] || 0 === imageNames[i].length) continue; - osSelect.append($('')); - } - } - os.append(osLabel); - os.append(osSelect); - osAttr.append(os); - - // Create boot method drop down - var bootMethod = $('
                  '); - var methoddLabel = $(''); - var methodSelect = $(''); - methodSelect.append('' - + '' - + '' - + '' - + '' - ); - bootMethod.append(methoddLabel); - bootMethod.append(methodSelect); - osAttr.append(bootMethod); - - // Generate tooltips - provExisting.find('div input[title],select[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" - } - }); - - /** - * Provision existing - */ - var provisionBtn = createButton('Provision'); - provisionBtn.bind('click', function(event) { - // Remove any warning messages - $(this).parent().parent().find('.ui-state-error').remove(); - - var ready = true; - var errMsg = ''; - - // Get provision tab ID - var thisTabId = $(this).parent().parent().parent().attr('id'); - // Get provision tab instance - var inst = thisTabId.replace('zvmProvisionTab', ''); - - // Get nodes that were checked - var dTableId = 'zNodesDatatable' + inst; - var tgts = getNodesChecked(dTableId); - if (!tgts) { - errMsg += 'You need to select a node.
                  '; - ready = false; - } - - // Check operating system image - var os = $('#' + thisTabId + ' select[name=os]:visible'); - if (!os.val()) { - errMsg += 'You need to select a operating system image.'; - os.css('border', 'solid #FF0000 1px'); - ready = false; - } else { - os.css('border', 'solid #BDBDBD 1px'); - } - - // If all inputs are valid, ready to provision - if (ready) { - // Disable provision button - $(this).attr('disabled', 'true'); - - // Show loader - $('#zProvisionStatBar' + inst).show(); - $('#zProvisionLoader' + inst).show(); - - // Disable all inputs - var inputs = $('#' + thisTabId + ' input:visible'); - inputs.attr('disabled', 'disabled'); - - // Disable all selects - var selects = $('#' + thisTabId + ' select'); - selects.attr('disabled', 'disabled'); - - // Get operating system image - var osImage = $('#' + thisTabId + ' select[name=os]:visible').val(); - var tmp = osImage.split('-'); - var os = tmp[0]; - var arch = tmp[1]; - var profile = tmp[3]; - - /** - * (1) Set operating system - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeadd', - tgt : '', - args : tgts + ';noderes.netboot=zvm;nodetype.os=' + os + ';nodetype.arch=' + arch + ';nodetype.profile=' + profile, - msg : 'cmd=nodeadd;out=' + inst - }, - - success : updateZProvisionExistingStatus - }); - } else { - // Show warning message - var warn = createWarnBar(errMsg); - warn.prependTo($(this).parent().parent()); - } - }); - provExisting.append(provisionBtn); - - return provExisting; -} - -/** - * Create provision new node division - * - * @param inst Provision tab instance - * @return Provision new node division - */ -function createZProvisionNew(inst) { - if (typeof console == "object"){ - console.log("Entering createZProvisionNew. Inst value:"+inst); - } - // Create provision new node division - var provNew = $('
                  '); - - // Create VM fieldset - var vmFS = $('
                  '); - var vmLegend = $('Virtual Machine'); - vmFS.append(vmLegend); - provNew.append(vmFS); - - var vmAttr = $('
                  '); - vmFS.append($('
                  ')); - vmFS.append(vmAttr); - - // Create OS fieldset - var osFS = $('
                  '); - var osLegend = $('Operating System'); - osFS.append(osLegend); - provNew.append(osFS); - - // Create hardware fieldset - var hwFS = $('
                  '); - var hwLegend = $('Hardware'); - hwFS.append(hwLegend); - provNew.append(hwFS); - - var hwAttr = $('
                  '); - hwFS.append($('
                  ')); - hwFS.append(hwAttr); - - // Create tabs for basic and advanced hardware configuration - var hwTab = new Tab('hwConfig' + inst); - hwTab.init(); - hwAttr.append(hwTab.object()); - - var osAttr = $('
                  '); - osFS.append($('
                  ')); - osFS.append(osAttr); - - // Create group input - var group = $('
                  '); - var groupLabel = $(''); - var groupInput = $(''); - // Get groups on-focus - groupInput.one('focus', function(){ - var groupNames = $.cookie('xcat_groups'); - if (groupNames) { - // Turn on auto complete - $(this).autocomplete({ - source: groupNames.split(',') - }); - } - }); - group.append(groupLabel); - group.append(groupInput); - vmAttr.append(group); - - // Create node input - var nodeName = $('
                  '); - var nodeLabel = $(''); - var nodeInput = $(''); - nodeName.append(nodeLabel); - nodeName.append(nodeInput); - vmAttr.append(nodeName); - - // Create user ID input - var userId = $('
                  '); - vmAttr.append(userId); - - // Create hardware control point input - var hcpDiv = $('
                  '); - var hcpNodeLabel = $(''); - var hcpNodeInput = $(''); - var hcpHiddenInput = $(''); - hcpNodeInput.blur(function() { - - if (typeof console == "object") { - console.log("Display loading bar "); - } - // Show the status bar with a message and loading gif - $('#'+'zProvisionStatBar'+inst).find('div').append("Loading zhcp information..."); - $('#'+'zProvisionStatBar'+inst).find('div').append(""); - $('#'+'zProvisionStatBar'+inst).show(); - - // list of calls after the zhcp is verified. Used to determine when in progress gif is to be removed. - var ajaxCalls = {"diskpoolnames":1, "zfcppoolnames":1, "userprofilenames":1}; - var zhcpToCheck = $(this).val(); - var zhcpField = $(this); - var provisionStatusBar = $('#'+'zProvisionStatBar'+inst); - - // Make sure border is set back to black - zhcpField.css('border', 'solid #BDBDBD 1px'); - - if ($(this).val()) { - // Check if this is a valid node by making network names call. - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : zhcpToCheck, - args : '--getnetworknames', - msg : zhcpToCheck - }, - - success: function(data) { - if (data.rsp.length && (data.rsp[0].indexOf("Failed") > -1 || data.rsp[0].indexOf("Invalid") > -1 || data.rsp[0].indexOf("Error") > -1) ) { - // Remove the progress gif, since bailing out - removeProvisionLoadingGif(provisionStatusBar); - - // Create warning dialog - var warning = createWarnBar('Failure getting network data for hardware control point ' + zhcpToCheck + '
                  The hcp field must be a xCAT node name.'); - var warnDialog = $('
                  ').append(warning); - - // highlight the hcp field - zhcpField.css('border', 'solid #FF0000 1px'); - - // Open warning dialog - warnDialog.dialog({ - title:'Warning', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function() { - $(this).dialog("close"); - } - } - }); - - } else { - // Node is good, now set some cookies from network, then check/set other cookies - setNetworkCookies(data); - - // Get the HCP name from the hcp node name - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsdef', - tgt : '', - args : zhcpToCheck, - msg : 'zhcpFullName' - }, - - success: function(data) { - if (data.rsp.length && (data.rsp[0].indexOf("Failed") > -1 || data.rsp[0].indexOf("Invalid") > -1) ) { - // Remove the progress gif, since bailing out - removeProvisionLoadingGif(provisionStatusBar); - - // Create warning dialog - var warning = createWarnBar('Failure getting hcp data from hardware control point ' + zhcpToCheck + '
                  The hcp field must be a valid xCAT node name.'); - var warnDialog = $('
                  ').append(warning); - - // highlight the hcp field - zhcpField.css('border', 'solid #FF0000 1px'); - - // Open warning dialog - warnDialog.dialog({ - title:'Warning', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function() { - $(this).dialog("close"); - } - } - }); - } else { - // Now set the hidden hcp field with the full name - // Clear hash table containing definable node attributes - nodeAttrs = new Array(); - - // Get definable attributes - // Data returned - var rsp = data.rsp; - // Group name - var group = data.msg; - // Hash of node attributes - var attrs = new Object(); - - // Go through each attribute - var node, args; - for (var i in rsp) { - // Get node name, skip processing - if (rsp[i].indexOf('Object name:') > -1) { - i++; - } - - // Get key and value - args = rsp[i].split('=', 2); - var key = jQuery.trim(args[0]); - var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length)); - - // If this is zhcp key then save full name in hidden field - if (key == "hcp") { - hcpHiddenInput.val(val); - } - - } - - } - } - }); - - if (typeof console == "object"){ - console.log("Looking for cookies from <" + zhcpToCheck + ">"); - } - - if (!$.cookie('xcat_' + zhcpToCheck + 'diskpools')) { - // Get disk pools - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : zhcpToCheck, - args : '--diskpoolnames', - msg : zhcpToCheck - }, - - success : setDiskPoolCookies, - complete : function() { - checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "diskpoolnames"); - } - }); - } else { - checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "diskpoolnames"); - } - - if (!$.cookie('xcat_' + zhcpToCheck + 'zfcppools')) { - // Get zFCP pools - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : zhcpToCheck, - args : '--zfcppoolnames', - msg : zhcpToCheck - }, - - success : setZfcpPoolCookies, - complete : function() { - checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "zfcppoolnames"); - } - }); - } else { - checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "zfcppoolnames"); - } - - if (!$.cookie('xcat_' + zhcpToCheck + 'userprofiles')) { - // Get zFCP pools - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - async: false, - data : { - cmd : 'lsvm', - tgt : zhcpToCheck, - args : '--userprofilenames', - msg : zhcpToCheck - }, - - success : setUserProfilesCookies, - complete : function() { - checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "userprofilenames"); - } - }); - } else { - checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "userprofilenames"); - } - - // Reset user profile and network drop down box - var thisTabId = zhcpField.parents('.tab').attr('id'); - var thisUserProfile = $('#' + thisTabId + ' select[name=userProfile]'); - thisUserProfile.children().remove(); - - var definedUserProfiles = $.cookie('xcat_' + zhcpToCheck + 'userprofiles').split(','); - for (var i in definedUserProfiles) { - if( !definedUserProfiles[i] || 0 === definedUserProfiles[i].length) continue; - thisUserProfile.append(''); - } - - var thisNetwork = $('#' + thisTabId + ' select[name=network]'); - thisNetwork.children().remove(); - thisNetwork.append(''); // No profile option - var definedNetworks = $.cookie('xcat_' + zhcpToCheck + 'networks').split(','); - for (var i in definedNetworks) { - if( !definedNetworks[i] || 0 === definedNetworks[i].length) continue; - if (!jQuery.trim(definedNetworks[i])) - continue; - - var directoryEntry, interfaceName; - - // Generate directory entry statement for vSwitch, hipersocket, and guest LAN - if (definedNetworks[i].indexOf('VSWITCH ') != -1) { - interfaceName = jQuery.trim(definedNetworks[i].replace('VSWITCH ', '')); - directoryEntry = "TYPE QDIO LAN " + interfaceName; - } else if (definedNetworks[i].indexOf('LAN:HIPERS ') != -1) { - interfaceName = jQuery.trim(definedNetworks[i].replace('LAN:HIPERS ', '')); - directoryEntry = "TYPE HIPERSOCKETS LAN " + interfaceName; - } else { - interfaceName = jQuery.trim(definedNetworks[i].replace('LAN:QDIO ', '')); - directoryEntry = "TYPE QDIO LAN " + interfaceName; - } - - thisNetwork.append(''); - } - - // Update user entry on change - thisNetwork.change(function() { - updateUserEntry(thisTabId); - }); - - thisUserProfile.change(function() { - updateUserEntry(thisTabId); - }); - } - } - }); - } - }); - hcpDiv.append(hcpNodeLabel); - hcpDiv.append(hcpNodeInput); - hcpDiv.append(hcpHiddenInput); - vmAttr.append(hcpDiv); - - // Create an advanced link to set IP address and hostname - var advancedLnk = $(''); - vmAttr.append(advancedLnk); - var advanced = $('
                  ').hide(); - vmAttr.append(advanced); - - var ip = $('
                  '); - advanced.append(ip); - var hostname = $('
                  '); - advanced.append(hostname); - - // Show IP address and hostname inputs on-click - advancedLnk.click(function() { - advanced.toggle(); - }); - - // Create operating system image input - var os = $('
                  '); - var osLabel = $(''); - var osSelect = $(''); - osSelect.append($('')); - - var imageNames = $.cookie('xcat_imagenames').split(','); - if (imageNames) { - imageNames.sort(); - for (var i in imageNames) { - if( !imageNames[i] || 0 === imageNames[i].length) continue; - osSelect.append($('')); - } - } - os.append(osLabel); - os.append(osSelect); - osAttr.append(os); - - // Create user entry input - var defaultChkbox = $('').click(function() { - // Remove any warning messages - $(this).parents('.form').find('.ui-state-error').remove(); - - // Get tab Id - var thisTabId = $(this).parents('.ui-tabs-panel').parents('.ui-tabs-panel').attr('id'); - - // Get objects for HCP, user ID, and OS - var userId = $('#' + thisTabId + ' input[name=userId]'); - var os = $('#' + thisTabId + ' select[name=os]'); - - // Get default user entry when clicked - if ($(this).attr('checked')) { - if (!os.val() || !userId.val()) { - // Show warning message - var warn = createWarnBar('Please specify the operating system and user ID before checking this box'); - warn.prependTo($(this).parents('.form')); - - // Highlight empty fields - jQuery.each([os, userId], function() { - if (!$(this).val()) { - $(this).css('border', 'solid #FF0000 1px'); - } - }); - } else { - // Un-highlight empty fields - jQuery.each([os, userId], function() { - $(this).css('border', 'solid #BDBDBD 1px'); - }); - - // Get profile name - var tmp = os.val().split('-'); - var profile = tmp[3]; - - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'getdefaultuserentry;' + profile, - msg : thisTabId - }, - - success:function(data) { - // Populate user entry - var tabId = data.msg; - var entry = new String(data.rsp); - var userId = $('#' + tabId + ' input[name=userId]').val(); - entry = entry.replace(new RegExp('LXUSR', 'g'), userId); - $('#' + tabId + ' textarea:visible').val(entry); - } - }); - } - } else { - $('#' + thisTabId + ' textarea:visible').val(''); - - // Un-highlight empty fields - jQuery.each([os, userId], function() { - $(this).css('border', 'solid #BDBDBD 1px'); - }); - } - }); - var userEntry = $('
                  '); - userEntry.append($('').append(defaultChkbox, 'Use default')); - - // Add division on basic tab for specifying: memory, # of CPUs, privilege, user profile, and network. - var basicConfig = $('
                  '); - var userProfile = $('
                  '); - var cpuSelect = $('').change(function() { - updateUserEntry('zvmProvisionTab' + inst); - }); - var cpuCount = $('
                  ').append(cpuSelect); - var memorySlider = $('
                  '); - var memorySize = $(''); - var memory = $('
                  ').append(memorySlider, memorySize); - var acceptableMemorySize = ['512M', '1024M', '2G', '3G', '4G', '5G', '6G', '7G', '8G']; - memorySlider.slider({ - value: 0, - min: 0, - max: 8, - step: 1, - slide: function(event, ui) { - $('#basicConfig' + inst + ' input[name=memory]').val(acceptableMemorySize[ui.value]); - - // Update user entry on change - updateUserEntry('zvmProvisionTab' + inst); - } - }); - - // Initialize storage size - memorySize.val(acceptableMemorySize[0]); - - var privilege = $('
                  ' + - '
                  ' + - ' A - Primary system operator
                  ' + - ' B - System resource operator
                  ' + - ' C - System programmer
                  ' + - ' D - Spooling operator
                  ' + - ' E - System analyst
                  ' + - ' F - IBM service representative
                  ' + - ' G - General user
                  ' + - '
                  ' + - '
                  '); - privilege.find('input').change(function() { - updateUserEntry('zvmProvisionTab' + inst); - }); - - var network = $('
                  '); - - var vswitchvlan = $('

                  ' + - '
                  ' + - '
                  '); - vswitchvlan.find('input').change(function() { - updateUserEntry('zvmProvisionTab' + inst); - }); - vswitchvlan.find('select').change(function() { - updateUserEntry('zvmProvisionTab' + inst); - }); - - vswitchvlan.hide(); - basicConfig.append(userProfile, cpuCount, memory, privilege, network, vswitchvlan); - hwTab.add('basicConfig' + inst, 'Basic', basicConfig, false); - - // Add division on advanced tab for specifying user directory entry - hwTab.add('advancedConfig' + inst, 'Advanced', userEntry, false); - - // Create disk table - var diskDiv = $('
                  '); - var diskLabel = $(''); - var diskTable = $('
                  '); - var diskHeader = $(' Type Address Size Mode Pool Password IPLNone
                  '); - // Adjust header width - diskHeader.find('th').css( { - 'width' : '80px' - }); - diskHeader.find('th').eq(0).css( { - 'width' : '20px' - }); - var diskBody = $(''); - var diskFooter = $(''); - - /** - * Add disks - */ - var addDiskLink = $('Add disk'); - addDiskLink.bind('click', function(event) { - // Get list of disk pools - var thisTabId = $(this).parents('.tab').attr('id'); - var thisHcp = $('#' + thisTabId + ' input[name=hcp]').val(); - var definedPools = null; - if (thisHcp) { - // Get node without domain name - var temp = thisHcp.split('.'); - definedPools = $.cookie('xcat_' + temp[0] + 'diskpools').split(','); - } else { - var warning = createWarnBar('You must fill in a hardware control point before adding a disk.'); - var warnDialog = $('
                  ').append(warning); - - // Open dialog - warnDialog.dialog({ - title:'Warning', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function() { - $(this).dialog("close"); - } - } - }); - return false; - } - - // Create a row - var diskRow = $(''); - - // Add remove button - var removeBtn = $(''); - var col = $('').append(removeBtn); - removeBtn.bind('click', function(event) { - diskRow.remove(); - }); - diskRow.append(col); - - // Create disk type drop down - var diskType = $(''); - var diskTypeSelect = $(''); - diskTypeSelect.append('' - + '' - ); - diskType.append(diskTypeSelect); - diskRow.append(diskType); - - // Create disk address input - var diskAddr = $(''); - diskRow.append(diskAddr); - - // Create disk size input - var diskSize = $(''); - diskRow.append(diskSize); - - // Create disk mode input - var diskMode = $(''); - var diskModeSelect = $(''); - diskModeSelect.append('' - + '' - + '' - + '' - + '' - + '' - + '' - ); - diskMode.append(diskModeSelect); - diskRow.append(diskMode); - - // Create disk pool drop down - var diskPool = $(''); - var diskPoolSelect = $(''); - for (var i in definedPools) { - diskPoolSelect.append(''); - } - diskPool.append(diskPoolSelect); - diskRow.append(diskPool); - - // Create disk password input - var diskPw = $(''); - diskRow.append(diskPw); - - // Create IPL checkbox - //var diskIpl = $(''); - var diskIpl = $(''); - diskRow.append(diskIpl); - diskIpl.find('input').change(function() { - updateUserEntry(thisTabId); - }); - - diskBody.append(diskRow); - - // Generate tooltips - diskBody.find('td input[title],select[title]').tooltip({ - position: "top right", - offset: [-4, 4], - effect: "fade", - opacity: 0.7, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - } - }); - }); - - // Create disk table - diskFooter.append(addDiskLink); - diskTable.append(diskHeader); - diskTable.append(diskBody); - diskTable.append(diskFooter); - - diskDiv.append(diskLabel); - diskDiv.append(diskTable); - hwAttr.append(diskDiv); - - // Create zFCP table - var zfcpDiv = $('
                  '); - var zfcpLabel = $(''); - var zfcpTable = $('
                  '); - var zfcpHeader = $(' Address Size Pool Tag Port Name Unit # LOADDEV'); - // Adjust header width - zfcpHeader.find('th').css({ - 'width' : '80px' - }); - zfcpHeader.find('th').eq(0).css({ - 'width' : '20px' - }); - var zfcpBody = $(''); - var zfcpFooter = $(''); - - /** - * Add zFCP devices - */ - var addZfcpLink = $('Add zFCP'); - addZfcpLink.bind('click', function(event) { - // Get list of disk pools - var thisTabId = $(this).parents('.tab').attr('id'); - var thisHcp = $('#' + thisTabId + ' input[name=hcp]').val(); - var definedPools = null; - if (thisHcp) { - // Get node without domain name - var temp = thisHcp.split('.'); - definedPools = $.cookie('xcat_' + temp[0] + 'zfcppools').split(','); - } else { - var warning = createWarnBar('You must fill in a hardware control point before adding a zFCP.'); - var warnDialog = $('
                  ').append(warning); - - // Open dialog - warnDialog.dialog({ - title:'Warning', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function() { - $(this).dialog("close"); - } - } - }); - - } - - // Create a row - var zfcpRow = $(''); - - // Add remove button - var removeBtn = $(''); - var col = $('').append(removeBtn); - removeBtn.bind('click', function(event) { - zfcpRow.remove(); - }); - zfcpRow.append(col); - - // Create disk address input - var zfcpAddr = $(''); - zfcpRow.append(zfcpAddr); - - // Create disk size input - var zfcpSize = $(''); - zfcpRow.append(zfcpSize); - - // Create zFCP pool drop down - var zfcpPool = $(''); - var zfcpPoolSelect = $(''); - for (var i in definedPools) { - zfcpPoolSelect.append(''); - } - zfcpPool.append(zfcpPoolSelect); - zfcpRow.append(zfcpPool); - - // Create disk tag - var zfcpTag = $(''); - zfcpRow.append(zfcpTag); - - // Create device port name - var zfcpPortName = $(''); - zfcpRow.append(zfcpPortName); - - // Create device unit number - var zfcpUnitNo = $(''); - zfcpRow.append(zfcpUnitNo); - - // Create LOADDEV radio button - var zfcpLoaddev = $(''); - zfcpRow.append(zfcpLoaddev); - - zfcpBody.append(zfcpRow); - - // Generate tooltips - zfcpBody.find('td input[title],select[title]').tooltip({ - position: "top right", - offset: [-4, 4], - effect: "fade", - opacity: 0.7, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - } - }); - }); - - zfcpFooter.append(addZfcpLink); - zfcpTable.append(zfcpHeader); - zfcpTable.append(zfcpBody); - zfcpTable.append(zfcpFooter); - - zfcpDiv.append(zfcpLabel); - zfcpDiv.append(zfcpTable); - hwAttr.append(zfcpDiv); - - // Generate tooltips - provNew.find('div input[title],select[title],textarea[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" - } - }); - - // Disable IPL column if advanced tab is selected - hwTab.object().tabs({ - select: function(event, ui) { - // Get provision tab instance - var thisTabId = $(this).parents('.ui-tabs-panel').attr('id'); - var inst = thisTabId.replace('zvmProvisionTab', ''); - - // Disable and de-select IPL device - if (ui.index == 1) { - $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').attr('disabled','disabled'); - } else { - $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').removeAttr('disabled'); - } - - $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').removeAttr('checked'); - } - }); - - /** - * Provision new - */ - var provisionBtn = createButton('Provision'); - provisionBtn.bind('click', function(event) { - // Remove any warning messages - $(this).parent().parent().find('.ui-state-error').remove(); - - var ready = true; - var errMsg = ''; - - // Get tab ID - var thisTabId = $(this).parents('.ui-tabs-panel').attr('id'); - // Get provision tab instance - var inst = thisTabId.replace('zvmProvisionTab', ''); - - // Get the selected hardware configuration tab - // Basic tab index = 0 & advanced tab index = 1 - var hwTabIndex = $("#hwConfig" + inst).tabs('option', 'selected'); - - // Check node name, userId, hardware control point, and group - // Check disks and zFCP devices - var inputs = $('#' + thisTabId + ' input:visible'); - for (var i = 0; i < inputs.length; i++) { - // Do not check some inputs - if (inputs.eq(i).attr('name') == 'memory') { - // There should always be a value for memory - // Do not change the border - continue; - } else if (!inputs.eq(i).val() - && inputs.eq(i).attr('type') != 'password' - && inputs.eq(i).attr('name') != 'zfcpTag' - && inputs.eq(i).attr('name') != 'zfcpPortName' - && inputs.eq(i).attr('name') != 'zfcpUnitNo') { - inputs.eq(i).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - inputs.eq(i).css('border', 'solid #BDBDBD 1px'); - } - } - - var selects = $('#' + thisTabId + ' select:visible'); - for (var i = 0; i < selects.length; i++) { - if (!selects.eq(i).val() && selects.eq(i).attr('name') != 'os' && selects.eq(i).attr('name') != 'userProfile' && selects.eq(i).attr('name') != 'network') { - selects.eq(i).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - selects.eq(i).css('border', 'solid #BDBDBD 1px'); - } - } - - if (hwTabIndex == 1) { - // Check user entry - var thisUserEntry = $('#' + thisTabId + ' textarea:visible'); - thisUserEntry.val(thisUserEntry.val().toUpperCase()); - if (!thisUserEntry.val()) { - thisUserEntry.css('border', 'solid #FF0000 1px'); - ready = false; - } else { - thisUserEntry.css('border', 'solid #BDBDBD 1px'); - } - - // Check if user entry contains user ID - var thisUserId = $('#' + thisTabId + ' input[name=userId]:visible'); - var pos = thisUserEntry.val().indexOf('USER ' + thisUserId.val().toUpperCase()); - if (pos < 0) { - - pos = thisUserEntry.val().indexOf('IDENTITY ' + thisUserId.val().toUpperCase()); - if (pos < 0) { - errMsg = errMsg + 'The directory entry does not contain the correct user/identity ID.
                  '; - ready = false; - } - } - } - var hostnameCheck = $('#' + thisTabId + ' input[name=hostname]').val(); - if (hostnameCheck.length > 70) { - errMsg = errMsg + 'The host name cannot be longer than 70 characters.
                  '; - $('#' + thisTabId + ' input[name=hostname]').css('border', 'solid #FF0000 1px'); - ready = false; - } - - // Show error message for missing inputs - if (!ready) { - errMsg = errMsg + 'Please provide a value for each missing field.
                  '; - } - - // If no operating system is specified, create only user entry - os = $('#' + thisTabId + ' select[name=os]:visible'); - - // Check number of disks - var diskRows = $('#' + thisTabId + ' table tr'); - // If an OS is given, disks are needed - if (os.val() && (diskRows.length < 1)) { - errMsg = errMsg + 'You need to add at some disks.
                  '; - ready = false; - } - - // If this is basic mode, check for a disk with IPL radio button and zFCP with LOADDEV button - // Cannot have both. (In advanced mode they create the directory entries.) - if (hwTabIndex == 0) { - // Find a device to be IPLed? - var ECKD_FBA_diskRows = $('#' + thisTabId + ' table:eq(0):visible tbody tr'); - var iplSet = 0; - for (var i = 0; i < ECKD_FBA_diskRows.length; i++) { - var diskArgs = ECKD_FBA_diskRows.eq(i).find('td'); - if (diskArgs.eq(7).find('input').attr("checked") === true) { - iplSet = 1; - break; - } - } - - // Check if zFCP loaddev checked - var zfcpRows = $('#' + thisTabId + ' table:eq(1):visible tbody tr'); - if (zfcpRows.length > 0) { - for ( var i = 0; i < zfcpRows.length; i++) { - var diskArgs = zfcpRows.eq(i).find('td'); - // This is either true or false - var loaddev = diskArgs.eq(7).find('input').attr('checked'); - if (loaddev && iplSet) { - errMsg = errMsg + 'You cannot have both disk IPL and zFCP LOADDEV, can only IPL one device.
                  '; - ready = false; - } - } - } - } - - // If inputs are valid, ready to provision - if (ready) { - // Generate user directory entry if basic tab is selected - if (hwTabIndex == 0) { - updateUserEntry(thisTabId); - } - - if (!os.val()) { - // If no OS is given, create a virtual server - var msg = ''; - if (diskRows.length > 0) { - msg = 'Do you want to create a virtual server without an operating system?'; - } else { - // If no disks are given, create a virtual server (no disk) - msg = 'Do you want to create a virtual server without an operating system or disks?'; - } - - // Open dialog to confirm - var confirmDialog = $('

                  ' + msg + '

                  '); - confirmDialog.dialog({ - title:'Confirm', - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - "Ok": function(){ - // Disable provision button - provisionBtn.attr('disabled', 'true'); - - // Show loader - $('#zProvisionStatBar' + inst).show(); - $('#zProvisionLoader' + inst).show(); - - // Disable add disk button - addDiskLink.attr('disabled', 'true'); - - // Disable close button on disk table - $('#' + thisTabId + ' table span').unbind('click'); - - // Disable all inputs - var inputs = $('#' + thisTabId + ' input'); - inputs.attr('disabled', 'disabled'); - - // Disable all selects - var selects = $('#' + thisTabId + ' select'); - selects.attr('disabled', 'disabled'); - - // Add a new line at the end of the user entry - var textarea = $('#' + thisTabId + ' textarea'); - var tmp = jQuery.trim(textarea.val()); - textarea.val(tmp + '\n'); - textarea.attr('readonly', 'readonly'); - textarea.css( { - 'background-color' : '#F2F2F2' - }); - - // Get node name - var node = $('#' + thisTabId + ' input[name=nodeName]').val(); - // Get userId - var userId = $('#' + thisTabId + ' input[name=userId]').val(); - // Get hardware control point - var hcp = $('#' + thisTabId + ' input[name=hcp]').val(); - // Get group - var group = $('#' + thisTabId + ' input[name=group]').val(); - // Get IP address and hostname - var ip = $('#' + thisTabId + ' input[name=ip]').val(); - var hostname = $('#' + thisTabId + ' input[name=hostname]').val(); - - // Generate arguments to sent - var args = node + ';zvm.hcp=' + hcp - + ';zvm.userid=' + userId - + ';nodehm.mgt=zvm' - + ';groups=' + group; - if (ip) - args += ';hosts.ip=' + ip; - - if (hostname) - args += ';hosts.hostnames=' + hostname; - - /** - * (1) Define node - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeadd', - tgt : '', - args : args, - msg : 'cmd=nodeadd;out=' + inst - }, - - success : updateZProvisionNewStatus - }); - - $(this).dialog("close"); - }, - "Cancel": function() { - $(this).dialog("close"); - } - } - }); - } else { - /** - * Create a virtual server and install OS - */ - - // Disable provision button - $(this).attr('disabled', 'true'); - - // Show loader - $('#zProvisionStatBar' + inst).show(); - $('#zProvisionLoader' + inst).show(); - - // Disable add disk button - addDiskLink.attr('disabled', 'true'); - - // Disable close button on disk table - $('#' + thisTabId + ' table span').unbind('click'); - - // Disable all inputs - var inputs = $('#' + thisTabId + ' input'); - inputs.attr('disabled', 'disabled'); - inputs.css( { - 'background-color' : '#F2F2F2' - }); - - // Disable all selects - var selects = $('#' + thisTabId + ' select'); - selects.attr('disabled', 'disabled'); - selects.css( { - 'background-color' : '#F2F2F2' - }); - - // Add a new line at the end of the user entry - var textarea = $('#' + thisTabId + ' textarea'); - var tmp = jQuery.trim(textarea.val()); - textarea.val(tmp + '\n'); - textarea.attr('readonly', 'readonly'); - textarea.css( { - 'background-color' : '#F2F2F2' - }); - - // Get node name - var node = $('#' + thisTabId + ' input[name=nodeName]').val(); - // Get userId - var userId = $('#' + thisTabId + ' input[name=userId]').val(); - // Get hardware control point - var hcp = $('#' + thisTabId + ' input[name=hcp]').val(); - // Get group - var group = $('#' + thisTabId + ' input[name=group]').val(); - // Get IP address and hostname - var ip = $('#' + thisTabId + ' input[name=ip]').val(); - var hostname = $('#' + thisTabId + ' input[name=hostname]').val(); - - // Generate arguments to sent - var args = node + ';zvm.hcp=' + hcp - + ';zvm.userid=' + userId - + ';nodehm.mgt=zvm' - + ';groups=' + group; - if (ip) - args += ';hosts.ip=' + ip; - - if (hostname) - args += ';hosts.hostnames=' + hostname; - - /** - * (1) Define node - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeadd', - tgt : '', - args : args, - msg : 'cmd=nodeadd;out=' + inst - }, - - success : updateZProvisionNewStatus - }); - } - } else { - // Show warning message - var warn = createWarnBar(errMsg); - warn.prependTo($(this).parent().parent()); - } - }); - provNew.append(provisionBtn); - - return provNew; -} -/** - * Remove zprovision loading gif for zhcp and message - * - * @param division holding the gif and message - */ -function removeProvisionLoadingGif(provisionStatBar) { - - // Only remove the status bar message and gif we added, then hide the status bar - var items = provisionStatBar.find('div').children(); - for (var i = 0; i< items.length; i++) { - var nname = items[i].nodeName; - var myid = items[i].id; - if (nname == "B" && myid == "loadzhcp") { - items[i].remove() - } else if (nname == "IMG" && myid == "loadingpic") { - items[i].remove(); - } - } - provisionStatBar.hide(); -} - -/** - * Set hash entry to 0 and check if all are 0. If so call - * removeProvisionLoadingGif - * - * @param division holding the gif and message, and hash, and - * key - */ -function checkProvisionCallsDone(provisionStatBar, table, finishedKey) { - - table[finishedKey] = 0; - - for (var key in table) { - if (table[key] == 1) { - return; // More to do - } - } - - removeProvisionLoadingGif(provisionStatBar); -} - -/** - * Load zVMs into column (service page) - * - * @param col Table column where OS images will be placed - */ -function loadzVMs(col) { - // Get group names and description and append to group column - if (!$.cookie('xcat_zvms')) { - var infoBar = createInfoBar('No selectable z/VM available'); - col.append(infoBar); - return; - } - - var zNames = $.cookie('xcat_zvms').split(','); - - var radio, zBlock, args, zvm, hcp; - for (var i in zNames) { - if( !zNames[i] || 0 === zNames[i].length) continue; - args = zNames[i].split(':'); - zvm = args[0]; - hcp = args[1]; - - // Create block for each group - zBlock = $('
                  ').css({ - 'border': '1px solid', - 'max-width': '200px', - 'margin': '5px auto', - 'padding': '5px', - 'display': 'block', - 'vertical-align': 'middle', - 'cursor': 'pointer', - 'white-space': 'normal' - }).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'); - zBlock.append(radio, $('' + zvm + ' managed by ' + hcp + '')); - zBlock.children('span').css({ - 'display': 'block', - 'margin': '5px', - 'text-align': 'left' - }); - col.append(zBlock); - } -} - -/** - * Load groups into column - * - * @param col Table column where OS images will be placed - */ -function loadSrvGroups(col) { - // Get group names and description and append to group column - if (!$.cookie('xcat_srv_groups')) { - var infoBar = createInfoBar('No selectable group available'); - col.append(infoBar); - return; - } - - var groupNames = $.cookie('xcat_srv_groups').split(','); - - var groupBlock, radio, args, name, ip, hostname, desc; - for (var i in groupNames) { - if( !groupNames[i] || 0 === groupNames[i].length) continue; - 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': 'block', - 'vertical-align': 'middle', - 'cursor': 'pointer', - 'white-space': 'normal' - }).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 + ': ' + desc + '')); - groupBlock.children('span').css({ - 'display': 'block', - 'margin': '5px', - 'text-align': 'left' - }); - col.append(groupBlock); - } -} - -/** - * Load OS images into column - * - * @param col Table column where OS images will be placed - */ -function loadOSImages(col) { - // Get group names and description and append to group column - if (!$.cookie('xcat_srv_imagenames')) { - var infoBar = createInfoBar('No selectable image available'); - col.append(infoBar); - return; - } - - var imgNames = $.cookie('xcat_srv_imagenames').split(','); - - var imgBlock, radio, args, name, desc; - for (var i in imgNames) { - if( !imgNames[i] || 0 === imgNames[i].length) continue; - 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': 'block', - 'vertical-align': 'middle', - 'cursor': 'pointer', - 'white-space': 'normal' - }).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'); - - $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').attr('checked', ''); - $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').parents('td').find('div').attr('class', 'ui-state-default'); - }); - radio = $('').css('display', 'none'); - imgBlock.append(radio, $('' + name + ': ' + desc + '')); - imgBlock.children('span').css({ - 'display': 'block', - 'margin': '5px', - 'text-align': 'left' - }); - col.append(imgBlock); - } -} - -/** - * Load golden images into column - * - * @param col Table column where master copies will be placed - */ -function loadGoldenImages(col) { - // Get group names and description and append to group column - if (!$.cookie('xcat_srv_goldenimages')) { - var infoBar = createInfoBar('No selectable master copies available'); - col.append(infoBar); - return; - } - - var imgNames = $.cookie('xcat_srv_goldenimages').split(','); - - var imgBlock, radio, args, name, desc; - for (var i in imgNames) { - if( !imgNames[i] || 0 === imgNames[i].length) continue; - 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': 'block', - 'vertical-align': 'middle', - 'cursor': 'pointer', - 'white-space': 'normal' - }).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'); - - // Un-select zVM and image - $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').attr('checked', ''); - $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').parents('td').find('div').attr('class', 'ui-state-default'); - - $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').attr('checked', ''); - $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').parents('td').find('div').attr('class', 'ui-state-default'); - }); - radio = $('').css('display', 'none'); - imgBlock.append(radio, $('' + name + ': ' + desc + '')); - imgBlock.children('span').css({ - 'display': 'block', - 'margin': '5px', - 'text-align': 'left' - }); - col.append(imgBlock); - } -} - -/** - * Set a cookie for zVM host names (service page) - * - * @param data Data from HTTP request - */ -function setzVMCookies(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - var zvms = new Array(); - var hosts = data.rsp[0].split("\n"); - for ( var i = 0; i < hosts.length; i++) { - if (hosts[i] != null && hosts[i] != "") { - zvms.push(hosts[i]); - if (typeof console == "object"){ - console.log("Setting a zVM cookie:<"+hosts[i]+">"); - } - } - } - - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); - $.cookie('xcat_zvms', zvms, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Set a cookie for master copies (service page) - * - * @param data Data from HTTP request - */ -function setGoldenImagesCookies(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - var copies = new Array(); - var tmp = data.rsp[0].split(","); - for ( var i = 0; i < tmp.length; i++) { - if (tmp[i] != null && tmp[i] != "") { - copies.push(tmp[i]); - } - } - - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); - $.cookie('xcat_srv_goldenimages', copies, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Set a cookie for disk pool names of a given node - * - * @param data Data from HTTP request - */ -function setDiskPoolCookies(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - var node = data.msg; - var pools = data.rsp[0].split(node + ": "); - var pools2 = []; - for (var j in pools) { - if (pools[j] != "") { - pools2.push(jQuery.trim(pools[j])); - } - } - - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); - $.cookie('xcat_' + node + 'diskpools', pools2, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Set a cookie for zFCP pool names of a given node - * - * @param data Data from HTTP request - */ -function setZfcpPoolCookies(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - var node = data.msg; - var pools = data.rsp[0].split(node + ': '); - var pools2 = []; - for (var j in pools) { - if (pools[j] != "") { - pools2.push(jQuery.trim(pools[j])); - } - } - - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); - $.cookie('xcat_' + node + 'zfcppools', pools2, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Set a cookie for zHCP host names - * - * @param zhcps List of zHCPs known - */ -function setzHcpCookies(zhcps) { - if (zhcps.length) { - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); - $.cookie('xcat_zhcps', zhcps, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Set a cookie for z/VM user profile names of a given node - * - * @param data Data from HTTP request - */ -function setUserProfilesCookies(data) { - if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { - var node = data.msg; - var profiles = data.rsp[0].split(node + ': '); - var profiles2 = []; - for (var j in profiles) { - if (profiles[j] != "") { - profiles2.push(jQuery.trim(profiles[j])); - } - } - - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); - $.cookie('xcat_' + node + 'userprofiles', profiles2, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Create virtual machine (service page) - * - * @param tabId Tab ID - * @param group Group - * @param hcp Hardware control point - * @param img OS image - */ -function createzVM(tabId, group, hcp, img, owner) { - // Submit request to create VM - // webportal provzlinux [group] [hcp] [image] [owner] - var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=provzlinux;' + group + ';' + hcp + ';' + img + ';' + owner + '&msg=&opts=flush'); - iframe.prependTo($('#' + tabId)); -} - -/** - * Query the profiles that exists - * - * @param panelId Panel ID - */ -function queryProfiles(panelId) { - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : 'osimage', - msg : panelId - }, - - success : function(data) { - var panelId = data.msg; - setOSImageCookies(data); - configProfilePanel(panelId); - } - }); -} - -/** - * Panel to configure directory entries and disks for a profile - * - * @param panelId Panel ID - */ -function configProfilePanel(panelId) { - // Wipe panel clean - $('#' + panelId).empty(); - - // Add info bar - $('#' + panelId).append(createInfoBar('Create, edit, and delete profiles for the self-service portal. It is important to note the default z/VM user ID for any profile should be LXUSR.')); - - // Create table - var tableId = 'zvmProfileTable'; - var table = new DataTable(tableId); - table.init(['', 'Profile', 'Disk pool', 'Disk size', 'Directory entry']); - - // Insert profiles into table - var profiles = $.cookie('xcat_profiles').split(','); - profiles.push('default'); // Add default profile - for (var i in profiles) { - if (profiles[i]) { - // Columns are: profile, selectable, description, disk pool, disk size, and directory entry - var cols = new Array(profiles[i], '', '', ''); - - // Add remove button where id = user name - cols.unshift(''); - - // Add row - table.add(cols); - } - } - - // Append datatable to tab - $('#' + panelId).append(table.object()); - - // Turn into datatable - $('#' + tableId).dataTable({ - 'iDisplayLength': 50, - 'bLengthChange': false, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - - // Create action bar - var actionBar = $('
                  ').css("width", "450px"); - - // Create a profile - var createLnk = $('Create'); - createLnk.click(function() { - profileDialog(); - }); - - // Edit a profile - var editLnk = $('Edit'); - editLnk.click(function() { - var profiles = $('#' + tableId + ' input[type=checkbox]:checked'); - for (var i in profiles) { - var profile = profiles.eq(i).attr('name'); - if (profile) { - // Column order is: profile, selectable, disk pool, disk size, and directory entry - var cols = profiles.eq(i).parents('tr').find('td'); - var pool = cols.eq(2).text(); - var size = cols.eq(3).text(); - var entry = cols.eq(4).html().replace(new RegExp('
                  ', 'g'), '\n'); - - editProfileDialog(profile, pool, size, entry); - } - } - }); - - // Delete a profile - var deleteLnk = $('Delete'); - deleteLnk.click(function() { - var profiles = getNodesChecked(tableId); - if (profiles) { - deleteProfileDialog(profiles); - } - }); - - // Refresh profiles table - var refreshLnk = $('Refresh'); - refreshLnk.click(function() { - queryProfiles(panelId); - }); - - // Create an action menu - var actionsMenu = createMenu([refreshLnk, createLnk, editLnk, deleteLnk]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + tableId + '_wrapper').prepend(menuDiv); - menuDiv.append(actionBar); - $('#' + tableId + '_filter').appendTo(menuDiv); - - // Resize accordion - $('#' + tableId).parents('.ui-accordion').accordion('resize'); - - // Query directory entries and disk pool/size for each profile - for (var i in profiles) { - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'getdefaultuserentry;' + profiles[i], - msg : 'out=' + panelId + ';profile=' + profiles[i] - }, - - success: insertDirectoryEntry - }); - - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'getzdiskinfo;' + profiles[i], - msg : 'out=' + panelId + ';profile=' + profiles[i] - }, - - success: insertDiskInfo - }); - } -} - -/** - * Insert the directory entry into the profile table - * - * @param data Data from HTTP request - */ -function insertDirectoryEntry(data) { - var tableId = 'zvmProfileTable'; - var args = data.msg.split(';'); - - var profile = args[1].replace('profile=', ''); - - // Do not continue if there is nothing - if (!data.rsp.length) - return; - - var entry = data.rsp[0].replace(new RegExp('\n', 'g'), '
                  '); - - // Get the row containing the profile - var rowPos = findRow(profile, '#' + tableId, 1); - if (rowPos < 0) - return; - - // Update the directory entry column - var dTable = $('#' + tableId).dataTable(); - dTable.fnUpdate(entry, rowPos, 4, false); - - // Adjust table styling - $('#' + tableId + ' td:nth-child(5)').css({ - 'text-align': 'left' - }); - adjustColumnSize(tableId); -} - -/** - * Insert the disk info into the profile table - * - * @param data Data from HTTP request - */ -function insertDiskInfo(data) { - var tableId = 'zvmProfileTable'; - var args = data.msg.split(';'); - - var profile = args[1].replace('profile=', ''); - - // Do not continue if there is nothing - if (!data.rsp.length) - return; - - // Get the row containing the profile - var rowPos = findRow(profile, '#' + tableId, 1); - if (rowPos < 0) - return; - - // Update the disk info columns - var dTable = $('#' + tableId).dataTable(); - - var tmp = ""; - var pool = ""; - var eckdSize = 0; - var info = data.rsp[0].split('\n'); - for (var i in info) { - if (info[i].indexOf('diskpool') > -1) { - tmp = info[i].split('='); - pool = jQuery.trim(tmp[1]); - - dTable.fnUpdate(pool, rowPos, 2, false); - } if (info[i].indexOf('eckd_size') > -1) { - tmp = info[i].split('='); - eckdSize = jQuery.trim(tmp[1]); - - dTable.fnUpdate(eckdSize, rowPos, 3, false); - } - } - - // Adjust table styling - adjustColumnSize(tableId); -} - -/** - * Open profile dialog - */ -function profileDialog() { - // Create form to add profile - var dialogId = 'zvmCreateProfile'; - var profileForm = $('
                  '); - - // Create info bar - var info = createInfoBar('Configure the default settings for a profile'); - profileForm.append(info); - - // Insert profiles into select - var profileSelect = $(''); - var profiles = $.cookie('xcat_profiles').split(','); - profiles.push('default'); // Add default profile - for (var i in profiles) { - if (profiles[i]) { - profileSelect.append($('')); - } - } - - profileForm.append($('
                  ').append(profileSelect)); - profileForm.append('
                  '); - profileForm.append('
                  '); - profileForm.append('
                  '); + for ( var i = 1; i < userEntry.length; i++) { + userEntry[i] = jQuery.trim(userEntry[i]); + txtArea.append(userEntry[i]); + + if (i < userEntry.length) { + txtArea.append('\n'); + } + } + txtArea.attr('readonly', 'readonly'); + fieldSet.append(txtArea); + + /** + * Edit user entry + */ + txtArea.bind('dblclick', function(event) { + txtArea.attr('readonly', ''); + txtArea.css( { + 'border-width' : '1px' + }); + + saveBtn.show(); + cancelBtn.show(); + saveBtn.css('display', 'inline-table'); + cancelBtn.css('display', 'inline-table'); + }); + + /** + * Save + */ + var saveBtn = createButton('Save').hide(); + saveBtn.bind('click', function(event) { + // Show loader + $('#' + node + 'StatusBarLoader').show(); + $('#' + node + 'StatusBar').show(); + + // Replace user entry + var newUserEntry = jQuery.trim(txtArea.val()) + '\n'; + + // Replace user entry + $.ajax( { + url : 'lib/zCmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--replacevs', + att : newUserEntry, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process and save it in a cookie + incrementNodeProcess(node); + + txtArea.attr('readonly', 'readonly'); + txtArea.css( { + 'border-width' : '0px' + }); + + // Disable save button + $(this).hide(); + cancelBtn.hide(); + }); + + /** + * Cancel + */ + var cancelBtn = createButton('Cancel').hide(); + cancelBtn.bind('click', function(event) { + txtArea.attr('readonly', 'readonly'); + txtArea.css( { + 'border-width' : '0px' + }); + + cancelBtn.hide(); + saveBtn.hide(); + }); + + // Create info bar + var infoBar = createInfoBar('Double click on the directory entry to edit it.'); + + // Append user entry into division + $('#' + ueDivId).append(infoBar); + $('#' + ueDivId).append(fieldSet); + $('#' + ueDivId).append(saveBtn); + $('#' + ueDivId).append(cancelBtn); +} + +/** + * Increment number of processes running against a node + * + * @param node Node to increment running processes + */ +function incrementNodeProcess(node) { + // Get current processes + var procs = $.cookie('xcat_' + node + 'processes'); + if (procs) { + // One more process + procs = parseInt(procs) + 1; + $.cookie('xcat_' + node + 'processes', procs); + } else { + $.cookie('xcat_' + node + 'processes', 1); + } +} + +/** + * Update provision new node status + * + * @param data Data returned from HTTP request + */ +function updateZProvisionNewStatus(data) { + // Parse ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + var lastCmd = args[0].replace('cmd=', ''); + var out2Id = args[1].replace('out=', ''); + if (typeof console == "object"){ + console.log("Entering updateZProvisionNewStatus. Last command:<"+lastCmd+"> All args:<"+args+">"); + } + // IDs for status bar, tab, and loader + var statBarId = 'zProvisionStatBar' + out2Id; + var tabId = 'zvmProvisionTab' + out2Id; + var loaderId = 'zProvisionLoader' + out2Id; + + var node = $('#' + tabId + ' input[name=nodeName]').val(); + + /** + * (2) Create user entry + */ + if (lastCmd == 'nodeadd') { + if (rsp.length) { + $('#' + loaderId).hide(); + $('#' + statBarId).find('div').append('
                  (Error) Failed to create node definition
                  '); + } else { + $('#' + statBarId).find('div').append('
                  Node definition created for ' + node + '
                  '); + + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + + // Create user entry + var userEntry = $('#' + tabId + ' textarea').val(); + $.ajax( { + url : 'lib/zCmd.php', + dataType : 'json', + data : { + cmd : 'mkvm', + tgt : node, + args : '', + att : userEntry, + msg : 'cmd=mkvm;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + + /** + * (3) Update /etc/hosts + */ + else if (lastCmd == 'mkvm') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + + // If there was an error, quit + if (containErrors(prg.html())) { + $('#' + loaderId).hide(); + } else { + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makehosts', + tgt : '', + args : '', + msg : 'cmd=makehosts;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + + /** + * If sourceforge xcat: (4) Update DNS + */ + else if ((lastCmd == 'makehosts') && (builtInXCAT == 0)) { + // If there was an error, quit + if (rsp.length) { + $('#' + loaderId).hide(); + $('#' + statBarId).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); + } else { + $('#' + statBarId).find('div').append('
                  /etc/hosts updated
                  '); + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makedns', + tgt : '', + args : '', + msg : 'cmd=makedns;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + /** + * If built in zVM xcat and last command was makehosts or + * If sourceforge xCAT and lastCmd was makedns + * (5) Add disk + * + */ + else if (((lastCmd == 'makehosts') && (builtInXCAT == 1)) || + ((lastCmd == 'makedns') && (builtInXCAT == 0))) { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + + // If there was an error, quit + if (rsp.length) { + $('#' + loaderId).hide(); + if (builtInXCAT == 1) { + $('#' + statBarId).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); + } else { + $('#' + statBarId).find('div').append('
                  (Error) Failed to makedns
                  '); + } + } else { + if (builtInXCAT == 1) { + $('#' + statBarId).find('div').append('
                  /etc/hosts updated
                  '); + } else { + $('#' + statBarId).find('div').append('
                  makedns updated
                  '); + } + + // Set cookie for number of disks + var diskRows = $('#' + tabId + ' table:eq(0):visible tbody tr'); + $.cookie('xcat_disks2add' + out2Id, diskRows.length, {path: '/xcat', secure:true }); + if (diskRows.length > 0) { + for (var i = 0; i < diskRows.length; i++) { + var diskArgs = diskRows.eq(i).find('td'); + var type = diskArgs.eq(1).find('select').val(); + var address = diskArgs.eq(2).find('input').val(); + var size = diskArgs.eq(3).find('input').val(); + var mode = diskArgs.eq(4).find('select').val(); + var pool = diskArgs.eq(5).find('select').val(); + var password = diskArgs.eq(6).find('input').val(); + + // Create ajax arguments + var args = ''; + if (type == '3390') { + args = '--add' + type + ';' + pool + ';' + address + + ';' + size + ';' + mode + ';' + password + ';' + + password + ';' + password; + } else if (type == '9336') { + args = '--add' + type + ';' + pool + ';' + address + ';' + + size + ';' + mode + ';' + password + ';' + + password + ';' + password; + } + + // Attach disk to node + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : args, + msg : 'cmd=chvm-disk;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + + // Set cookie for number of zFCP devices + var zfcpRows = $('#' + tabId + ' table:eq(1):visible tbody tr'); + $.cookie('xcat_zfcp2add' + out2Id, zfcpRows.length, {path: '/xcat', secure:true }); + if (zfcpRows.length > 0) { + for ( var i = 0; i < zfcpRows.length; i++) { + var diskArgs = zfcpRows.eq(i).find('td'); + var address = diskArgs.eq(1).find('input').val(); + var size = diskArgs.eq(2).find('input').val(); + var pool = diskArgs.eq(3).find('select').val(); + var tag = diskArgs.eq(4).find('input').val(); + var portName = diskArgs.eq(5).find('input').val(); + var unitNo = diskArgs.eq(6).find('input').val(); + + // This is either true or false + var loaddev = diskArgs.eq(7).find('input').attr('checked'); + if (loaddev) { + loaddev = "1"; + } else { + loaddev = "0"; + } + + // Create ajax arguments + var args = '--addzfcp;' + pool + ';' + address + ';' + loaddev + ';' + size; + if (tag && tag != "null") { + args += ';' + tag; + } else { + args += ';'; + } + if (portName && tag != "null") { + args += ';' + portName; + } else { + args += ';'; + } if (unitNo && tag != "null") { + args += ';' + unitNo; + } else { + args += ';'; + } + + // Attach zFCP device to node + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : args, + msg : 'cmd=chvm-zfcp;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + + // Done if no disks to add + if (diskRows.length < 1 && zfcpRows.length < 1) { + $('#' + statBarId).find('div').append('
                  No disks found to provison, finished.
                  '); + $('#' + loaderId).hide(); + } + } + } + + /** + * (6) Set operating system for given node + */ + else if (lastCmd == 'chvm-disk' || lastCmd == 'chvm-zfcp') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + + // If there was an error, quit + if (containErrors(prg.html())) { + $('#' + loaderId).hide(); + } else { + // Set cookie for number of disks + // One less disk to add + var disks2add = $.cookie('xcat_disks2add' + out2Id); + if (lastCmd == 'chvm-disk') { + if (disks2add > 0) { + disks2add--; + $.cookie('xcat_disks2add' + out2Id, disks2add, {path: '/xcat', secure:true }); + } + } + + var zfcp2add = $.cookie('xcat_zfcp2add' + out2Id); + if (lastCmd == 'chvm-zfcp') { + if (zfcp2add > 0) { + zfcp2add--; + $.cookie('xcat_zfcp2add' + out2Id, zfcp2add, {path: '/xcat', secure:true }); + } + } + + // Only set operating system if there are no more disks to add + if (zfcp2add < 1 && disks2add < 1) { + // If an operating system image is given + var osImage = $('#' + tabId + ' select[name=os]:visible').val(); + if (osImage) { + // Get operating system, architecture, provision method, and profile + var tmp = osImage.split('-'); + var os = tmp[0]; + var arch = tmp[1]; + var profile = tmp[3]; + + // If the last disk is added + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : node + ';noderes.netboot=zvm;nodetype.os=' + + os + ';nodetype.arch=' + arch + + ';nodetype.profile=' + profile, + msg : 'cmd=noderes;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } else { + $('#' + loaderId).hide(); + } + } + } + } + + /** + * (7) If sourceforge xCAT Update DHCP + */ + else if ((lastCmd == 'noderes') && (builtInXCAT == 0)) { + // If there was an error, do not continue + if (rsp.length) { + $('#' + loaderId).hide(); + $('#' + statBarId).find('div').append('
                  (Error) Failed to set operating system
                  '); + } else { + $('#' + statBarId).find('div').append('
                  Operating system for ' + node + ' set
                  '); + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makedhcp', + tgt : '', + args : '-a', + msg : 'cmd=makedhcp;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + + /** + * (8) Prepare node for boot + */ + else if (((lastCmd == 'noderes') && (builtInXCAT == 1)) || + ((lastCmd == 'makedhcp') && (builtInXCAT == 0))) { + // If there was an error, do not continue + if (rsp.length) { + $('#' + loaderId).hide(); + if (builtInXCAT == 1) { + $('#' + statBarId).find('div').append('
                  (Error) Failed to set operating system
                  '); + } else { + $('#' + statBarId).find('div').append('
                  (Error) Failed to make dhcp
                  '); + } + } else { + if (builtInXCAT == 1) { + $('#' + statBarId).find('div').append('
                  Operating system for ' + node + ' set
                  '); + } else { + $('#' + statBarId).find('div').append('
                  DHCP for ' + node + ' set
                  '); + } + + // Prepare node for boot + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeset', + tgt : node, + args : 'install', + msg : 'cmd=nodeset;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + + /** + * (9) Boot node to network + */ + else if (lastCmd == 'nodeset') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + + // If there was an error + // Do not continue + if (containErrors(prg.html())) { + $('#' + loaderId).hide(); + } else { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rnetboot', + tgt : node, + args : 'ipl=000C', + msg : 'cmd=rnetboot;out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } + + /** + * (10) Done + */ + else if (lastCmd == 'rnetboot') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + if (prg.html().indexOf('Error') < 0) { + $('#' + statBarId).find('div').append('
                  Open a VNC viewer to see the installation progress.  It might take a couple of minutes before you can connect.
                  '); + } + + // Hide loader + $('#' + loaderId).hide(); + } +} + +/** + * Update the provision existing node status + * + * @param data Data returned from HTTP request + */ +function updateZProvisionExistingStatus(data) { + // Get ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + + // Get command invoked + var cmd = args[0].replace('cmd=', ''); + // Get provision tab instance + var inst = args[1].replace('out=', ''); + if (typeof console == "object"){ + console.log("Entering updateZProvisionExistingStatus. Last command:<"+cmd+"> All args:<"+args+">"); + } + + // Get provision tab and status bar ID + var statBarId = 'zProvisionStatBar' + inst; + var tabId = 'zvmProvisionTab' + inst; + + /** + * (2) Prepare node for boot + */ + if (cmd == 'nodeadd') { + // Get operating system + var bootMethod = $('#' + tabId + ' select[name=bootMethod]').val(); + + // Get nodes that were checked + var dTableId = 'zNodesDatatable' + inst; + var tgts = getNodesChecked(dTableId); + + // Prepare node for boot + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeset', + tgt : tgts, + args : bootMethod, + msg : 'cmd=nodeset;out=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionExistingStatus(data); + } + }); + } + + /** + * (3) Boot node from network + */ + else if (cmd == 'nodeset') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + + // If there was an error, do not continue + if (containErrors(prg.html())) { + var loaderId = 'zProvisionLoader' + inst; + $('#' + loaderId).remove(); + return; + } + + // Get nodes that were checked + var dTableId = 'zNodesDatatable' + inst; + var tgts = getNodesChecked(dTableId); + + // Boot node from network + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rnetboot', + tgt : tgts, + args : 'ipl=000C', + msg : 'cmd=rnetboot;out=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionExistingStatus(data); + } + }); + } + + /** + * (4) Done + */ + else if (cmd == 'rnetboot') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + if (prg.html().indexOf('Error') < 0) { + $('#' + statBarId).find('div').append('
                  Open a VNC viewer to see the installation progress.  It might take a couple of minutes before you can connect.
                  '); + } + + var loaderId = 'zProvisionLoader' + inst; + $('#' + loaderId).remove(); + } +} + +/** + * Update zVM node status + * + * @param data Data returned from HTTP request + */ +function updateZNodeStatus(data) { + var node = data.msg; + var rsp = data.rsp; + + // Get cookie for number processes performed against this node + var actions = $.cookie('xcat_' + node + 'processes'); + // One less process + actions = actions - 1; + $.cookie('xcat_' + node + 'processes', actions, {path: '/xcat', secure:true }); + + if (actions < 1) { + // Hide loader when there are no more processes + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).hide(); + } + + var statBarId = node + 'StatusBar'; + + // Write ajax response to status bar + var prg = writeRsp(rsp, node + ': '); + $('#' + statBarId).find('div').append(prg); +} + +/** + * Update clone status + * + * @param data Data returned from HTTP request + */ +function updateZCloneStatus(data) { + // Get ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + var cmd = args[0].replace('cmd=', ''); + + // Get provision instance + var inst = args[1].replace('inst=', ''); + // Get output division ID + var out2Id = args[2].replace('out=', ''); + + /** + * (2) Update /etc/hosts + */ + if (cmd == 'nodeadd') { + var node = args[3].replace('node=', ''); + + // If there was an error, do not continue + if (rsp.length) { + $('#' + out2Id).find('img').hide(); + $('#' + out2Id).find('div').append('
                  (Error) Failed to create node definition
                  '); + } else { + $('#' + out2Id).find('div').append('
                  Node definition created for ' + node + '
                  '); + + // If last node definition was created + var tmp = inst.split('/'); + if (tmp[0] == tmp[1]) { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makehosts', + tgt : '', + args : '', + msg : 'cmd=makehosts;inst=' + inst + ';out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZCloneStatus(data); + } + }); + } + } + } + + /** + * (3a) Update DNS if source forge xCAT then do makedns + */ + else if ((cmd == 'makehosts') && (builtInXCAT == 0)) { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + out2Id).find('div').append(prg); + + // If there was an error, do not continue + if (rsp.length) { + $('#' + out2Id).find('img').hide(); + $('#' + out2Id).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); + } else { + $('#' + out2Id).find('div').append('
                  /etc/hosts updated
                  '); + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makedns', + tgt : '', + args : '', + msg : 'cmd=makedns;inst=' + inst + ';out=' + out2Id + }, + + success : function(data) { + data = decodeRsp(data); + updateZCloneStatus(data); + } + }); + } + } + + /** + * (3b) Update DNS for built in xCAT and clone + * Just clone for sourceforge xCAT + */ + else if (((cmd == 'makehosts') && (builtInXCAT == 1)) || + ((cmd == 'makedns') && (builtInXCAT == 0))) { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + out2Id).find('div').append(prg); + + // If there was an error, do not continue + if (rsp.length) { + $('#' + out2Id).find('img').hide(); + if (builtInXCAT == 1) { + $('#' + out2Id).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); + } else { + $('#' + out2Id).find('div').append('
                  (Error) Failed to makedns
                  '); + } + } + // Get clone tab + var tabId = out2Id.replace('CloneStatusBar', 'CloneTab'); + + // If a node range is given + var tgtNodeRange = $('#' + tabId + ' input[name=tgtNode]').val(); + var tgtNodes = ''; + if (tgtNodeRange.indexOf('-') > -1) { + var tmp = tgtNodeRange.split('-'); + + // Get node base name + var nodeBase = tmp[0].match(/[a-zA-Z]+/); + // Get the starting index + var nodeStart = parseInt(tmp[0].match(/\d+/)); + // Get the ending index + var nodeEnd = parseInt(tmp[1].match(/\d+/)); + for ( var i = nodeStart; i <= nodeEnd; i++) { + // Do not append comma for last node + if (i == nodeEnd) { + tgtNodes += nodeBase + i.toString(); + } else { + tgtNodes += nodeBase + i.toString() + ','; + } + } + } else { + tgtNodes = tgtNodeRange; + } + + // Get other inputs + var srcNode = $('#' + tabId + ' input[name=srcNode]').val(); + hcp = $('#' + tabId + ' input[name=newHcp]').val(); + var group = $('#' + tabId + ' input[name=newGroup]').val(); + var diskPool = $('#' + tabId + ' input[name=diskPool]').val(); + var diskPw = $('#' + tabId + ' input[name=diskPw]').val(); + if (!diskPw) { + diskPw = ''; + } + + // Clone + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'mkvm', + tgt : tgtNodes, + args : srcNode + ';pool=' + diskPool + ';pw=' + diskPw, + msg : 'cmd=mkvm;inst=' + inst + ';out=' + out2Id + }, + error: function(jqXHR, textStatus) { + $('#' + out2Id).find('div').append('
                  (Error) Failed in clone call with ' + textStatus + '
                  '); + }, + success : function(data) { + data = decodeRsp(data); + updateZCloneStatus(data); + } + }); + } + + /** + * (5) Done + */ + else if (cmd == 'mkvm') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + out2Id).find('div').append(prg); + + // Hide loader + $('#' + out2Id).find('img').hide(); + } +} + +/** + * Get zVM resources + * + * @param data Data from HTTP request + */ +function getZResources(data) { + var tabId = 'zvmResourceTab'; + var info = createInfoBar('Manage storage and networks'); + $('#' + tabId).append(info); + + // Do not continue if there is no output + if (data.rsp.length) { + if (typeof console == "object"){ + console.log("Entering getZResources."); + } + // Push hardware control points into an array + var node, hcp; + var hcpHash = new Object(); + var hostnameHash = new Object(); + for (var i in data.rsp) { + node = data.rsp[i][0]; + hcp = data.rsp[i][1]; + // data will be coming in like "xcat xcat.endicott.ibm.com hosts.hostnames" + // or xcat zhcp.endicott.ibm.com zvm.hcp" + if (data.rsp[i][2]== "zvm.hcp") { + hcpHash[hcp] = 1; + } else { + if (hcp.length) { + hostnameHash[hcp] = node; + } + } + } + + // Create an array for hardware control points + var hcps = new Array(); + for (var key in hcpHash) { + // Get the short host name + //hcp = key.split('.')[0]; //old code + hcp = hostnameHash[key]; + if (typeof console == "object"){ + console.log("getZResources lookup for hostname "+key+" found nodename <"+hcp+">"); + } + if (jQuery.inArray(hcp, hcps) == -1) { + hcps.push(hcp); + } + } + + // Set hardware control point cookie + $.cookie('xcat_hcp', hcps, {path: '/xcat', secure:true }); + + // Delete loader + $('#' + tabId).find('img[src="images/loader.gif"]').remove(); + + // Create accordion panel for disk + var resourcesAccordion = $('
                  '); + var diskSection = $('
                  '); + var diskLnk = $('

                  Disks

                  ').click(function () { + // Do not load panel again if it is already loaded + if ($('#zvmDiskResource').children().length) { + return; + } + else + $('#zvmDiskResource').append(createLoader('')); + + // Resize accordion + $('#zvmResourceAccordion').accordion('resize'); + + // Create a array for hardware control points + var hcps = new Array(); + if ($.cookie('xcat_hcp').indexOf(',') > -1) { + hcps = $.cookie('xcat_hcp').split(','); + } else { + hcps.push($.cookie('xcat_hcp')); + } + + // Query the disk pools for each hcp + var panelId = 'zvmDiskResource'; + var info = $('#' + panelId).find('.ui-state-highlight'); + if (!info.length) { + info = createInfoBar("Querying "+hcps.length+" zhcp(s) for disk pools."); + $('#' + panelId).append(info); + } + zhcpQueryCountForDisks = hcps.length; + + for (var i in hcps) { + var itemcount = +i + 1; + info.append("
                  Querying disk pools from: "+hcps[i]+" ("+itemcount+" of "+hcps.length+")"); + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcps[i], + args : '--diskpoolnames', + msg : hcps[i] + }, + + success : function(data) { + data = decodeRsp(data); + getDiskPool(data); + } + }); + zhcpQueryCountForDisks--; + } + }); + + // Create accordion panel for zFCP devices + var zfcpSection = $('
                  '); + var zfcpLnk = $('

                  zFCP

                  ').click(function () { + // Do not load panel again if it is already loaded + if ($('#zfcpResource').children().length) + return; + else + $('#zfcpResource').append(createLoader('')); + + // Resize accordion + $('#zvmResourceAccordion').accordion('resize'); + + // Create a array for hardware control points + var hcps = new Array(); + if ($.cookie('xcat_hcp').indexOf(',') > -1) { + hcps = $.cookie('xcat_hcp').split(','); + } else { + hcps.push($.cookie('xcat_hcp')); + + } + + // Query the fcp pools for each hcp + var panelId = 'zfcpResource'; + var info = $('#' + panelId).find('.ui-state-highlight'); + if (!info.length) { + info = createInfoBar("Querying "+hcps.length+" zhcp(s) for fcp pools."); + $('#' + panelId).append(info); + } + zhcpQueryCountForZfcps = hcps.length; + for (var i in hcps) { + // Gather fcp pools from hardware control points + var itemcount = +i + 1; + info.append("
                  Querying fcp pools from: "+hcps[i]+" ("+itemcount+" of "+hcps.length+")"); + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcps[i], + args : '--zfcppoolnames', + msg : hcps[i] + }, + + success : function(data) { + data = decodeRsp(data); + getZfcpPool(data); + } + }); + zhcpQueryCountForZfcps--; + } + }); + + // Create accordion panel for network + var networkSection = $('
                  '); + var networkLnk = $('

                  Networks

                  ').click(function () { + // Do not load panel again if it is already loaded + if ($('#zvmNetworkResource').children().length) { + return; + } else { + $('#zvmNetworkResource').append(createLoader('')); + } + + // Resize accordion + $('#zvmResourceAccordion').accordion('resize'); + + // Create a array for hardware control points + var hcps = new Array(); + if ($.cookie('xcat_hcp').indexOf(',') > -1) { + hcps = $.cookie('xcat_hcp').split(','); + } else { + hcps.push($.cookie('xcat_hcp')); + + } + // Query the networks for each + var panelId = 'zvmNetworkResource'; + var info = $('#' + panelId).find('.ui-state-highlight'); + if (!info.length) { + info = createInfoBar("Querying "+hcps.length+" zhcp(s) for networks."); + $('#' + panelId).append(info); + } + zhcpQueryCountForNetworks = hcps.length; + for (var i in hcps) { + var itemcount = +i + 1; + info.append("
                  Querying networks from: "+hcps[i]+" ("+itemcount+" of "+hcps.length+")"); + $('#zvmResourceAccordion').accordion('resize'); + // Gather networks from hardware control points + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcps[i], + args : '--getnetworknames', + msg : hcps[i] + }, + + success : function(data) { + data = decodeRsp(data); + getNetwork(data); + } + }); + zhcpQueryCountForNetworks--; + } + }); + + resourcesAccordion.append(diskLnk, diskSection, zfcpLnk, zfcpSection, networkLnk, networkSection); + + // Append accordion to tab + $('#' + tabId).append(resourcesAccordion); + resourcesAccordion.accordion(); + networkLnk.trigger('click'); + } +} + +/** + * 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 = null; // 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 add processor dialog + * + * @param node Node to add processor to + */ +function openAddProcDialog(node) { + // Create form to add processor + var addProcForm = $('
                  '); + // Create info bar + var info = createInfoBar('Add a temporary processor to this virtual server.'); + addProcForm.append(info); + addProcForm.append('
                  '); + addProcForm.append('
                  '); + + // Create drop down for processor type + var procType = $('
                  '); + procType.append(''); + var typeSelect = $(''); + typeSelect.append('' + + '' + + '' + + '' + ); + procType.append(typeSelect); + addProcForm.append(procType); + + // Generate tooltips + addProcForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add processor + addProcForm.dialog({ + title:'Add processor', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var node = $(this).find('input[name=procNode]').val(); + var address = $(this).find('input[name=procAddress]').val(); + var type = $(this).find('select[name=procType]').val(); + + // If inputs are not complete, show warning message + if (!node || !address || !type) { + var warn = createWarnBar('Please provide a value for each missing field.'); + warn.prependTo($(this)); + } else { + // Add processor + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--addprocessoractive;' + address + ';' + type, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + var statusId = node + 'StatusBar'; + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).show(); + $('#' + statusId).show(); + + // Close dialog + $(this).dialog( "close" ); + } + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create add disk dialog + * + * @param node Node to add disk to + * @param hcp Hardware control point of node + */ +function openAddDiskDialog(node, hcp) { + // Get list of disk pools + var cookie = $.cookie('xcat_' + hcp + 'diskpools'); + var pools = new Array(); + if (cookie) { + pools = cookie.split(','); + } + + // Create form to add disk + var addDiskForm = $('
                  '); + // Create info bar + var info = createInfoBar('Add a ECKD|3390 or FBA|9336 disk to this virtual server.'); + addDiskForm.append(info); + addDiskForm.append('
                  '); + addDiskForm.append('
                  '); + addDiskForm.append('
                  '); + addDiskForm.append('
                  '); + + // Create drop down for disk pool + var diskPool = $('
                  '); + diskPool.append(''); + var poolSelect = $(''); + for ( var i = 0; i < pools.length; i++) { + if( !pools[i] || 0 === pools[i].length) continue; + poolSelect.append(''); + } + diskPool.append(poolSelect); + addDiskForm.append(diskPool); + + // Create drop down for disk mode + var diskMode = $('
                  '); + diskMode.append(''); + var modeSelect = $(''); + modeSelect.append('' + + '' + + '' + + '' + + '' + + '' + + '' + ); + diskMode.append(modeSelect); + addDiskForm.append(diskMode); + + addDiskForm.append('
                  '); + + // Generate tooltips + addDiskForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add disk + addDiskForm.dialog({ + title:'Add disk', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var node = $(this).find('input[name=diskNode]').val(); + var type = $(this).find('select[name=diskType]').val(); + var address = $(this).find('input[name=diskAddress]').val(); + var size = $(this).find('input[name=diskSize]').val(); + var pool = $(this).find('select[name=diskPool]').val(); + var mode = $(this).find('select[name=diskMode]').val(); + var password = $(this).find('input[name=diskPassword]').val(); + + // If inputs are not complete, show warning message + if (!node || !type || !address || !size || !pool || !mode) { + var warn = createWarnBar('Please provide a value for each missing field.'); + warn.prependTo($(this)); + } else { + // Add disk + if (type == '3390') { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--add3390;' + pool + ';' + address + ';' + size + + ';' + mode + ';' + password + ';' + password + ';' + password, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + var statusId = node + 'StatusBar'; + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).show(); + $('#' + statusId).show(); + } else if (type == '9336') { + // Default block size for FBA volumes = 512 + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--add9336;' + pool + ';' + address + ';' + size + + ';' + mode + ';' + password + ';' + password + ';' + password, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + var statusId = node + 'StatusBar'; + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).show(); + $('#' + statusId).show(); + } + + // Close dialog + $(this).dialog( "close" ); + } // End of else + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create add zFCP device dialog + * + * @param node Node to add disk to + * @param hcp Hardware control point of node + * @param zvm The z/VM system of node + */ +function openAddZfcpDialog(node, hcp, zvm) { + // Get list of disk pools + var cookie = $.cookie('xcat_' + hcp + 'zfcppools'); + var pools = new Array(); + if (cookie) { + pools = cookie.split(','); + } + + // Create form to add disk + var addZfcpForm = $('
                  '); + // Create info bar + var info = createInfoBar('Add a SCSI|FCP disk to this virtual server.'); + addZfcpForm.append(info); + addZfcpForm.append('
                  '); + addZfcpForm.append('
                  '); + addZfcpForm.append('
                  '); + addZfcpForm.append('
                  '); + + // Create drop down for disk pool + var diskPool = $('
                  '); + diskPool.append(''); + var poolSelect = $(''); + for ( var i = 0; i < pools.length; i++) { + if( !pools[i] || 0 === pools[i].length) continue; + poolSelect.append(''); + } + diskPool.append(poolSelect); + addZfcpForm.append(diskPool); + + // Tag to identify where device will be used + addZfcpForm.append('
                  '); + + // Create advanced link to set advanced zFCP properties + var advancedLnk = $(''); + addZfcpForm.append(advancedLnk); + var advanced = $('
                  ').hide(); + addZfcpForm.append(advanced); + + var portName = $('
                  '); + var unitNo = $('
                  '); + advanced.append(portName, unitNo); + + // Toggle port name and unit number when clicking on advanced link + advancedLnk.click(function() { + advanced.toggle(); + }); + + // Generate tooltips + addZfcpForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add disk + addZfcpForm.dialog({ + title:'Add zFCP device', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var node = $(this).find('input[name=diskNode]').val(); + var address = $(this).find('input[name=diskAddress]').val(); + var loaddev = $(this).find('input[name=diskLoaddev]'); + var size = $(this).find('input[name=diskSize]').val(); + var pool = $(this).find('select[name=diskPool]').val(); + var tag = $(this).find('input[name=diskTag]').val(); + var portName = $(this).find('input[name=diskPortName]').val(); + var unitNo = $(this).find('input[name=diskUnitNo]').val(); + + // If inputs are not complete, show warning message + if (!node || !address || !size || !pool) { + var warn = createWarnBar('Please provide a value for each missing field.'); + warn.prependTo($(this)); + } else { + if (loaddev.attr('checked')) { + loaddev = 1; + } else { + loaddev = 0; + } + + var args = '--addzfcp||' + pool + '||' + address + '||' + loaddev + '||' + size; + + if (tag && tag != "null") { + args += '||' + tag; + } else { + args += '|| ""'; + } + + if ((portName && portName != "null") && (unitNo && unitNo != "null")) { + args += '||' + portName + '||' + unitNo; + } + + // Add zFCP device + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : args, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + var statusId = node + 'StatusBar'; + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).show(); + $('#' + statusId).show(); + + // Close dialog + $(this).dialog( "close" ); + } + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create dedicate device dialog + * + * @param node Node to dedicate device to + * @param hcp Hardware control point of node + */ +function openDedicateDeviceDialog(node, hcp) { + // Create form to add disk + var dedicateForm = $('
                  '); + // Create info bar + var info = createInfoBar('Add a dedicated device to the configuration'); + dedicateForm.append(info); + + dedicateForm.append('
                  '); + dedicateForm.append('
                  '); + dedicateForm.append('
                  '); + dedicateForm.append('
                  '); + + // Generate tooltips + dedicateForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add dedicated device + dedicateForm.dialog({ + title:'Add dedicated device', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var node = $(this).find('input[name=diskNode]').val(); + var vAddress = $(this).find('input[name=virtualAddress]').val(); + var rAddress = $(this).find('input[name=realAddress]').val() + var mode = $(this).find('select[name=mode]').val(); + + // If inputs are not complete, show warning message + if (!node || !vAddress || !rAddress || !mode) { + var warn = createWarnBar('Please provide a value for each missing field.'); + warn.prependTo($(this)); + } else { + var args = '--dedicatedevice;' + vAddress + ';' + rAddress + ';' + mode; + + // Add zFCP device + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : args, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + var statusId = node + 'StatusBar'; + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).show(); + $('#' + statusId).show(); + + // Close dialog + $(this).dialog( "close" ); + } + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create add ECKD to system dialog + * + * @param hcp Hardware control point of node + */ +function openAddEckd2SystemDialog(hcp) { + var dialogId = 'zvmAddEckd2System'; + + // Create form to add disk + var addE2SForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + // Create info bar + var info = createInfoBar('Dynamically add an ECKD disk to a running z/VM system.'); + addE2SForm.append(info); + + addE2SForm.append(system); + addE2SForm.append('
                  '); + + // Generate tooltips + addE2SForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add disk + addE2SForm.dialog({ + title:'Add ECKD to system', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 420, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var system = $(this).find('select[name=system]').val(); + var devnum = $(this).find('input[name=devNum]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=devNum]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : "--addeckd;" + devnum, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create add Volume to system dialog + * + * @param hcp Hardware control point of node + */ +function openAddVolume2SystemDialog(hcp) { + var dialogId = 'zvmAddVolume2System'; + + // Create form to add volume + var addV2SForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + // Create info bar + var info = createInfoBar('Permanently add a volume to the z/VM system configuration.'); + addV2SForm.append(info); + + addV2SForm.append(system); + addV2SForm.append('
                  '); + addV2SForm.append('
                  '); + + // Generate tooltips + addV2SForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add volume + addV2SForm.dialog({ + title:'Add volume to system configuration', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 480, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var system = $(this).find('select[name=system]').val(); + var devnum = $(this).find('input[name=devNum]').val(); + var volser = $(this).find('input[name=volser]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=devNum]', 'input[name=volser]' ); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : "--addvolume;" + devnum + ";" + volser, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create remove Volume to system dialog + * + * @param hcp Hardware control point of node + */ +function openRemoveVolumeFromSystemDialog(hcp) { + var dialogId = 'zvmRemoveVolumeFromSystem'; + + // Create form to remove volume + var remVfromSForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + // Create info bar + var info = createInfoBar('Permanently remove a volume from the z/VM system configuration.'); + remVfromSForm.append(info); + + remVfromSForm.append(system); + remVfromSForm.append('
                  '); + remVfromSForm.append('
                  '); + + // Generate tooltips + remVfromSForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to remove volume + remVfromSForm.dialog({ + title:'Remove volume from system configuration', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 580, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var system = $(this).find('select[name=system]').val(); + var devnum = $(this).find('input[name=devNum]').val(); + var volser = $(this).find('input[name=volser]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=devNum]', 'input[name=volser]' ); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : "--removevolume;" + devnum + ";" + volser, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create add page or spool dialog + * + * @param hcp Hardware control point of node + */ +function openAddPageSpoolDialog(hcp) { + var dialogId = 'zvmAddPageSpool'; + + // Create form to add disk + var addPageSpoolForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + // Create info bar + var info = createInfoBar('Add a page or spool volume to be used by zVM.'); + addPageSpoolForm.append(info); + + var diskFS = $('
                  Disk
                  '); + addPageSpoolForm.append(diskFS); + var diskAttr = $('
                  '); + diskFS.append($('
                  ')); + diskFS.append(diskAttr); + + diskAttr.append(system); + diskAttr.append('
                  '); + diskAttr.append('
                  '); + diskAttr.append('
                  '); + + // Generate tooltips + addPageSpoolForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add disk + addPageSpoolForm.dialog({ + title:'Add page or spool', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 500, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var system = $(this).find('select[name=system]').val(); + var volAddr = $(this).find('input[name=volAddr]').val(); + var volLabel = $(this).find('input[name=volLabel]').val(); + var volUse = $(this).find('select[name=volUse]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=volAddr]', 'input[name=volLabel]', 'select[name=volUse]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + var pageSpoolArgs = volAddr + ";" + volLabel + ";" + volUse; + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : system, + args : '--addpagespool;' + pageSpoolArgs, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Open dialog to share disk + * + * @param disks2share Disks selected in table + */ +function openShareDiskDialog(disks2share) { + // Create form to share disk + var dialogId = 'zvmShareDisk'; + var shareDiskForm = $('
                  '); + + var args = disks2share.split(';'); + var tgtHcp = args[0]; + var tgtVol = args[1]; + + if (!tgtVol || tgtVol == "undefined") + tgtVol = ""; + + // Create info bar + var info = createInfoBar('Indicate a full-pack minidisk is to be shared by the users of many real and virtual systems.'); + shareDiskForm.append(info); + + // Set region input based on those selected on table (if any) + var node = $('
                  '); + var volAddr = $('
                  '); + var shareEnable = $('
                  '); + shareDiskForm.append(node, volAddr, shareEnable); + + // Generate tooltips + shareDiskForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to delete disk + shareDiskForm.dialog({ + title:'Share disk', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 500, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var node = $(this).find('input[name=node]').val(); + var volAddr = $(this).find('input[name=volAddr]').val(); + var shareEnable = $(this).find('select[name=shareEnable]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('input[name=node]', 'input[name=volAddr]', 'select[name=shareEnable]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + // Remove disk from pool + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : "--sharevolume;" + volAddr + ";" + shareEnable, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Create add SCSI 2 system dialog + * + * @param hcp Hardware control point of node + */ +function openAddScsi2SystemDialog(hcp) { + var dialogId = 'zvmAddScsi2System'; + + // Create form to add disk + var addS2SForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + // Create info bar + var info = createInfoBar('Dynamically add an SCSI disk to a running z/VM system as an EDEV.'); + addS2SForm.append(info); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + var devNo = $('
                  '); + var devPathLabel = $(''); + var devPathCount = 1; + //var pathDiv = $('
                  '); + + var devPathDiv = $('
                  '); + var devPathTable = $('
                  '); + var devPathHeader = $(' FCP Device WWPN LUN'); + // Adjust header width + devPathHeader.find('th').css({ + 'width' : '120px' + }); + devPathHeader.find('th').eq(0).css({ + 'width' : '20px' + }); + var devPathBody = $(''); + var devPathFooter = $(''); + + // Create a row + var devPathRow = $(''); + + // Add blank column (remove button replacement) + devPathRow.append(''); + + // Create FCP device number input + var fcpDevNum = $(''); + devPathRow.append(fcpDevNum); + + // Create FCP WWPN input + var fcpWwpn = $(''); + devPathRow.append(fcpWwpn); + + if ($.cookie('xcat_zvms')) { + zvms = $.cookie('xcat_zvms').split(','); + var zvm; + for (var i in zvms) { + if( !zvms[i] || 0 === zvms[i].length) continue; + var args = zvms[i].split(':'); + var zvm = args[0].toLowerCase(); + var iHcp = args[1]; + } + } + + // Create FCP LUN input + var fcpLun = $(''); + devPathRow.append(fcpLun); + + devPathBody.append(devPathRow); + + var addDevPathLink = $('+ Add path'); + addDevPathLink.bind('click', function(event){ + devPathCount = devPathCount + 1; + // Create a row + var devPathRow = $(''); + + // Add remove button + var removeBtn = $('').css({ + "float": "left", + "cursor": "pointer" + }); + var col = $('').append(removeBtn); + removeBtn.bind('click', function(event) { + $(this).parent().parent().remove(); + }); + devPathRow.append(col); + + // Create FCP device number input + var fcpDevNum = $(''); + devPathRow.append(fcpDevNum); + + // Create FCP WWPN input + var fcpWwpn = $(''); + devPathRow.append(fcpWwpn); + + // Create FCP LUN input + var fcpLun = $(''); + devPathRow.append(fcpLun); + + devPathBody.append(devPathRow); + + // Generate tooltips + addS2SForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + }); + devPathFooter.append(addDevPathLink); + devPathTable.append(devPathHeader); + devPathTable.append(devPathBody); + devPathTable.append(devPathFooter); + devPathDiv.append(devPathLabel); + devPathDiv.append(devPathTable); + + var option = $('
                  '); + var persist = $('
                  '); + addS2SForm.append(system, devNo, devPathDiv, option, persist); + + // Generate tooltips + addS2SForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + addS2SForm.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 to add disk + addS2SForm.dialog({ + title:'Add SCSI to running system', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 675, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var system = $(this).find('select[name=system]').val(); + var devNo = $(this).find('input[name=devNo]').val(); + var pathArray = ""; + jQuery('.devPath').each(function(index) { + pathArray += $(this).find('input[name=fcpDevNum]').val() + ','; + pathArray += $(this).find('input[name=fcpWwpn]').val() + ','; + pathArray += $(this).find('input[name=fcpLun]').val() + ';'; + }); + var option = $(this).find('select[name=option]').val(); + var persist = $(this).find('select[name=persist]').val(); + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=fcpDevNum]', 'select[name=option]', 'select[name=persist]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + // Show warning message + if (!ready || !pathArray) { + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : "--addscsi||" + devNo + "||" + pathArray + "||" + option + "||" + persist, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Delete a real SCSI disk + * + * @param hcp Hardware control point of node + */ +function openRemoveScsiDialog(hcp) { + var dialogId = 'zvmRemoveScsiDialog'; + // Create form to add disk + var removeScsiForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + // Create info bar + var info = createInfoBar('Delete a real SCSI disk'); + removeScsiForm.append(info, system); + removeScsiForm.append('
                  '); + removeScsiForm.append('
                  '); + addNicForm.append('
                  '); + + // Create drop down for NIC types + var nicType = $('
                  '); + nicType.append(''); + var nicTypeSelect = $(''); + nicTypeSelect.append('' + + '' + + '' + ); + nicType.append(nicTypeSelect); + addNicForm.append(nicType); + + // Create drop down for network types + var networkType = $('
                  '); + networkType.append(''); + var networkTypeSelect = $(''); + networkTypeSelect.append('' + + '' + + '' + ); + networkType.append(networkTypeSelect); + addNicForm.append(networkType); + var hashtable = getselectedNetworkHash(); + if (!hashtable) { + hashtable = [[]]; + setselectedNetworkHash(hashtable); + + if (typeof console == "object") { + console.log("openAddNicDialog. creating new hash[[]] table." ); + } + } + + // Create drop down for network names + var gLansQdioSelect = $(''); + var gLansHipersSelect = $(''); + var vswitchSelect = $(''); + for ( var i = 0; i < networks.length; i++) { + if( !networks[i] || 0 === networks[i].length) continue; + var network = networks[i].split(' '); + var networkOption = $(''); + if (network[0] == 'VSWITCH') { + vswitchSelect.append(networkOption); + + // Load and save specific vswitch details in global table if not there + network[2] = jQuery.trim(network[2]); // Remove new line x012 from end + if (typeof hashtable[node + '_NIC_' + network[2]] === 'undefined') { + if (typeof console == "object"){ + console.log("Calling getNetworkDetails for switch:<"+network[2]+">"); + } + ajaxrequest = 1; + getNetworkDetails(hcpNode, network[2], node + '_NIC_' + network[2], ''); + } + } else if (network[0] == 'LAN:QDIO') { + gLansQdioSelect.append(networkOption); + } else if (network[0] == 'LAN:HIPERS') { + gLansHipersSelect.append(networkOption); + } + } + + // Hide network name drop downs until the NIC type and network type is selected + // QDIO Guest LAN drop down + var guestLanQdio = $('
                  ').hide(); + guestLanQdio.append(''); + guestLanQdio.append(gLansQdioSelect); + addNicForm.append(guestLanQdio); + + // HIPERS Guest LAN drop down + var guestLanHipers = $('
                  ').hide(); + guestLanHipers.append(''); + guestLanHipers.append(gLansHipersSelect); + addNicForm.append(guestLanHipers); + + // VSWITCH drop down + var vswitch = $('
                  ').hide(); + vswitch.append(''); + vswitch.append(vswitchSelect); + + // VLAN id with Porttype + var vswitchvlan = $('
                  '); + vswitchvlan.append('
                  '); + var vswitchPorttype = $(''); + vswitchvlan.append(vswitchPorttype); + vswitchvlan.append('
                  '); + var vswitchVLANId = $(''); + vswitchvlan.append(vswitchVLANId); + + vswitch.append(vswitchvlan); + vswitchvlan.hide(); + addNicForm.append(vswitch); + + // Show network names on change + networkTypeSelect.change(function(){ + // Remove any warning messages + $(this).parent().parent().find('.ui-state-error').remove(); + var networkType = $(this).val(); + + if (typeof console == "object"){ + console.log("Entering networkTypeSelect.change"); + } + // Get NIC type and network type + var nicType = $(this).parent().parent().find('select[name=nicType]').val(); + var networkType = $(this).val(); + + // Hide network name drop downs + var guestLanQdio = $(this).parent().parent().find('select[name=nicLanQdioName]').parent(); + var guestLanHipers = $(this).parent().parent().find('select[name=nicLanHipersName]').parent(); + var vswitch = $(this).parent().parent().find('select[name=nicVSwitchName]').parent(); + var mynode = $(this).parent().parent().find('input[name=nicNode]').val(); + var showvlan = $(this).parent().parent().find('select[name=vswitchVLANporttype]').parent(); + var hashtable = getselectedNetworkHash(); + guestLanQdio.hide(); + guestLanHipers.hide(); + vswitch.hide(); + + // Show correct network name + if (networkType == 'Guest LAN' && nicType == 'QDIO') { + guestLanQdio.show(); + } else if (networkType == 'Guest LAN' && nicType == 'HiperSockets') { + guestLanHipers.show(); + } else if (networkType == 'Virtual Switch') { + if (nicType == 'QDIO') { + vswitch.show(); + // Show vlan information only if vlan aware + var switchname = $(this).parent().parent().find('select[name=nicVSwitchName]').val(); + var tokens = switchname.split(' '); + var switchkeyid = mynode + '_NIC_' + jQuery.trim(tokens[1]); + if (typeof console == "object"){ + console.log("Checking vswitch index:"+switchkeyid); + } + + // Is this a vlanaware switch, if so show the special fields + if (hashtable[switchkeyid]["vlan_awareness"] == "AWARE") { + showvlan.find('input[name=vswitchvlanid]').val(hashtable[switchkeyid]["vlan_id"]); + showvlan.find('select[name=vswitchVLANporttype]').val(hashtable[switchkeyid]["port_type"]); + showvlan.show(); + } else { + showvlan.hide(); + showvlan.find('input[name=vswitchvlanid]').val('default'); + showvlan.find('select[name=vswitchVLANporttype]').val('default'); + } + } else { + // No such thing as HIPERS VSWITCH + var warn = createWarnBar('The selected choices are not valid.'); + warn.prependTo($(this).parent().parent()); + } + } + }); + + // + // Show network names on change + // + nicTypeSelect.change(function(){ + // Remove any warning messages + $(this).parent().parent().find('.ui-state-error').remove(); + + if (typeof console == "object"){ + console.log("Entering nicTypeSelect.change"); + } + + // Get NIC type and network type + var nicType = $(this).val(); + var networkType = $(this).parent().parent().find('select[name=nicNetworkType]').val(); + var mynode = $(this).parent().parent().find('input[name=nicNode]').val(); + + // Hide network name drop downs + var guestLanQdio = $(this).parent().parent().find('select[name=nicLanQdioName]').parent(); + var guestLanHipers = $(this).parent().parent().find('select[name=nicLanHipersName]').parent(); + var vswitch = $(this).parent().parent().find('select[name=nicVSwitchName]').parent(); + var showvlan = $(this).parent().parent().find('select[name=vswitchVLANporttype]').parent(); + var hashtable = getselectedNetworkHash(); + guestLanQdio.hide(); + guestLanHipers.hide(); + vswitch.hide(); + + // Show correct network name + if (networkType == 'Guest LAN' && nicType == 'QDIO') { + guestLanQdio.show(); + } else if (networkType == 'Guest LAN' && nicType == 'HiperSockets') { + guestLanHipers.show(); + } else if (networkType == 'Virtual Switch') { + if (nicType == 'QDIO') { + vswitch.show(); + var switchname = $(this).parent().parent().find('select[name=nicVSwitchName]').val(); + var tokens = switchname.split(' '); + var switchkeyid = mynode + '_NIC_' + jQuery.trim(tokens[1]); + + if (typeof console == "object"){ + console.log("Entering nictypeselect.change. switchkey:<"+switchkeyid); + } + + // Is this a vlanaware switch, if so show the special fields + if (hashtable[switchkeyid]["vlan_awareness"] == "AWARE") { + showvlan.find('input[name=vswitchvlanid]').val(hashtable[switchkeyid]["vlan_id"]); + showvlan.find('select[name=vswitchVLANporttype]').val(hashtable[switchkeyid]["port_type"]); + showvlan.show(); + } else { + showvlan.hide(); + showvlan.find('input[name=vswitchvlanid]').val('default'); + showvlan.find('select[name=vswitchVLANporttype]').val('default'); + } + + } else { + // No such thing as HIPERS VSWITCH + var warn = createWarnBar('The selected choices are not valid.'); + warn.prependTo($(this).parent().parent()); + } + } + }); + + // + // Determine if vlanid fields need to be shown based on vswitch + // + vswitchSelect.change(function(){ + // Remove any warning messages + $(this).parent().parent().find('.ui-state-error').remove(); + + // Get vlan id division + var showvlan = $(this).parent().parent().find('select[name=vswitchVLANporttype]').parent(); + + // Get selected switch name and break it into tokens + var switchname = $(this).val(); + var tokens = switchname.split(' '); + + // Get the node we are doing this for and index for hash table + var mynode = $(this).parent().parent().find('input[name=nicNode]').val(); + + var tokens = switchname.split(' '); + var switchkeyid = mynode + '_NIC_' + jQuery.trim(tokens[1]); + var hashtable = getselectedNetworkHash(); + + if (typeof console == "object"){ + console.log("Entering vswitchselect.change. switchkey:<"+switchkeyid+">"); + } + // Is this a vlanaware switch, if so show the special fields + if (hashtable[switchkeyid]["vlan_awareness"] == "AWARE") { + $(this).find('').val(hashtable[switchkeyid]["vlan_id"]); + showvlan.find('input[name=vswitchvlanid]').val(hashtable[switchkeyid]["vlan_id"]); + showvlan.find('select[name=vswitchVLANporttype]').val(hashtable[switchkeyid]["port_type"]); + showvlan.show(); + } else { + showvlan.hide(); + showvlan.find('input[name=vswitchvlanid]').val('default'); + showvlan.find('select[name=vswitchVLANporttype]').val('default'); + } + }); + + + // Generate tooltips + addNicForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + + // Open dialog to add NIC + addNicForm.dialog({ + title:'Add NIC', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var ready = true; + var errMsg = ''; + + // Get inputs + var node = $(this).find('input[name=nicNode]').val(); + var nicType = $(this).find('select[name=nicType]').val(); + var networkType = $(this).find('select[name=nicNetworkType]').val(); + var address = $(this).find('input[name=nicAddress]').val(); + + // If inputs are not complete, show warning message + if (!node || !nicType || !networkType || !address) { + errMsg = 'Please provide a value for each missing field.
                  '; + ready = false; + } + + // If a HIPERS VSWITCH is selected, show warning message + if (nicType == 'HiperSockets' && networkType == 'Virtual Switch') { + errMsg += 'The selected choices are not valid.'; + ready = false; + } + + // If there are errors + if (!ready) { + // Show warning message + var warn = createWarnBar(errMsg); + warn.prependTo($(this)); + } else { + // Add guest LAN + if (networkType == 'Guest LAN') { + var temp; + if (nicType == 'QDIO') { + temp = $(this).find('select[name=nicLanQdioName]').val().split(' '); + } else { + temp = $(this).find('select[name=nicLanHipersName]').val().split(' '); + } + + var lanOwner = temp[0]; + var lanName = temp[1]; + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--addnic;' + address + ';' + nicType + ';3', + msg : 'node=' + node + ';addr=' + address + ';lan=' + + lanName + ';owner=' + lanOwner + }, + success : function(data) { + data = decodeRsp(data); + connect2GuestLan(data); + } + }); + } + + // Add virtual switch + else if (networkType == 'Virtual Switch' && nicType == 'QDIO') { + var temp = $(this).find('select[name=nicVSwitchName]').val().split(' '); + var vswitchName = jQuery.trim(temp[1]); + var switchkeyid = node + '_NIC_' + vswitchName; + var hashtable = getselectedNetworkHash(); + var awareornot = hashtable[switchkeyid]["vlan_awareness"]; + var porttype = $(this).find('select[name=vswitchVLANporttype]').val(); + var lanid = $(this).find('input[name=vswitchvlanid]').val(); + + // Pass additional lanid data in msg for grant use by connect2VSwitch + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--addnic;' + address + ';' + nicType + ';3', + msg : 'node=' + node + ';addr=' + address + ';vsw=' + + vswitchName + ';vlanaware=' + awareornot + ';porttype=' + + porttype + ';lanid=' + lanid + }, + + success : function(data) { + data = decodeRsp(data); + connect2VSwitch(data); + } + }); + } + + // Increment node process + incrementNodeProcess(node); + + // Show loader + $('#' + node + 'StatusBarLoader').show(); + $('#' + node + 'StatusBar').show(); + + // Close dialog + $(this).dialog( "close" ); + } // End of else + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); + // Make sure ajax is done before putting up dialog + $(document).ajaxStop(function() { + //Remove loading vswitch gif status bar + statBar.hide(); + }); + if (ajaxrequest == 0) { + //Remove loading vswitch gif status bar + statBar.hide(); + } + +} + +/** + * Create add vSwitch/VLAN dialog + * + * @param hcp Hardware control point of node + */ +function openAddVswitchVlanDialog(hcp) { + var dialogId = 'zvmAddVswitchVlan'; + + // Create form to add disk + var addVswitchForm = $('
                  '); + + // Create info bar + var info = createInfoBar('Create a virtual switch or virtual network LAN.'); + + var netFS = $('
                  '); + var netLegend = $('Network'); + netFS.append(netLegend); + + var typeFS = $('
                  ').hide(); + var typeLegend = $('Network'); + typeFS.append(typeLegend); + addVswitchForm.append(info, netFS, typeFS); + + var netAttr = $('
                  '); + netFS.append($('
                  ')); + netFS.append(netAttr); + + var networkTypeDiv = $('
                  '); + var networkType = $('
                  '); + networkTypeDiv.append(networkType) + netAttr.append(networkTypeDiv); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + netAttr.append(system); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + var typeAttr = $('
                  '); + typeFS.append($('
                  ')); + typeFS.append(typeAttr); + + // Create vSwitch parameters + var vswitchOptions = $('
                  ').hide(); + vswitchOptions.append($('
                  ')); + vswitchOptions.append($('
                  ')); + vswitchOptions.append($('
                  ')); + + // Create an advanced link to configure optional network settings + var advancedLnk = $(''); + vswitchOptions.append(advancedLnk); + var advanced = $('
                  ').hide(); + vswitchOptions.append(advanced); + + // Show IP address and hostname inputs on-click + advancedLnk.click(function() { + advanced.toggle(); + }); + + advanced.append($('
                  ')); + advanced.append($('
                  ')); + advanced.append($('
                  ')); + advanced.append($('
                  ')); + advanced.append($('
                  ')); + advanced.append($('
                  ')); + advanced.append($('
                  ')); + advanced.append($('
                  ')); + advanced.append($('
                  ')); + + // Create VLAN parameters + var vlanOptions = $('
                  ').hide(); + vlanOptions.append($('
                  ')); + vlanOptions.append($('
                  ')); + vlanOptions.append($('
                  ')); + vlanOptions.append($('
                  ')); + + typeAttr.append(vswitchOptions, vlanOptions); + + networkType.change(function() { + typeFS.show(); + if ($(this).val() == "vswitch") { + typeFS.find("legend").text("vSwitch"); + vswitchOptions.show(); + vlanOptions.hide(); + } else if ($(this).val() == "vlan") { + typeFS.find("legend").text("VLAN"); + vswitchOptions.hide(); + vlanOptions.show(); + } else { + typeFS.find("legend").text(""); + vswitchOptions.hide(); + vlanOptions.hide(); + typeFS.hide(); + } + }); + + // Generate tooltips + addVswitchForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add vSwitch or VLAN + addVswitchForm.dialog({ + title:'Add vSwitch or VLAN', + modal: true, + close: function() { + $(this).remove(); + }, + width: 750, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var networkType = $(this).find('select[name=networkType]').val(); + if (networkType == "vswitch") { + var networkArgs = "--addvswitch;"; + var system = $(this).find('select[name=system]').val(); + var switchName = $(this).find('input[name=switchName]').val(); + var deviceAddress = $(this).find('input[name=deviceAddress]').val(); + var portName = switchName; + var controllerName = $(this).find('input[name=controllerName]').val(); + var connection = $(this).find('select[name=connection]').val(); + var queueMemoryLimit = $(this).find('input[name=queueMemoryLimit]').val(); + var routingValue = $(this).find('select[name=routingValue]').val(); + var transportType = $(this).find('select[name=transportType]').val(); + var vlanId = $(this).find('input[name=vlanId]').val(); + var portType = $(this).find('select[name=vswitchVLANporttype]').val(); + var updateSysConfig = $(this).find('select[name=updateSysConfig]').val(); + var gvrp = $(this).find('select[name=gvrp]').val(); + var nativeVlanId = $(this).find('input[name=nativeVlanId]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=switchName]', 'input[name=deviceAddress]', 'input[name=controllerName]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + // Show warning message + if (!ready) { + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + if (switchName) + networkArgs += switchName + ";"; + if (deviceAddress) + networkArgs += deviceAddress + ";"; + if (portName) + networkArgs += portName + ";"; + if (controllerName) + networkArgs += controllerName + ";"; + + // Optional parameters + if (connection) + networkArgs += connection + ";"; + if (queueMemoryLimit) + networkArgs += queueMemoryLimit + ";"; + if (routingValue) + networkArgs += routingValue + ";"; + if (transportType) + networkArgs += transportType + ";"; + if (vlanId) + networkArgs += vlanId + ";"; + if (portType) + networkArgs += portType + ";"; + if (updateSysConfig) + networkArgs += updateSysConfig + ";"; + if (gvrp) + networkArgs += gvrp + ";"; + if (nativeVlanId) + networkArgs += nativeVlanId + ";"; + networkArgs = networkArgs.substring(0, networkArgs.length - 1); + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : networkArgs, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + } else if (networkType == "vlan") { + var networkArgs = "--addvlan;"; + var system = $(this).find('select[name=system]').val(); + var vlanName = $(this).find('input[name=vlanName]').val(); + var vlanOwner = $(this).find('input[name=vlanOwner]').val(); + var vlanType = $(this).find('select[name=vlanType]').val(); + var vlanTransport = $(this).find('select[name=vlanTransport]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=vlanName]', 'input[name=vlanOwner]', 'select[name=vlanType]', 'select[name=vlanTransport]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + // Show warning message + if (!ready) { + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Ethernet Hipersockets are not supported + if (vlanTransport == "2") { + var warn = createWarnBar('Ethernet Hipersockets are not supported'); + warn.prependTo($(this)); + return; + } + + networkArgs += vlanName + ";"; + networkArgs += vlanOwner + ";"; + networkArgs += vlanType + ";"; + networkArgs += vlanTransport; + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : networkArgs, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + } // End of else if + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Open dialog to delete network + * + * @param node type name for removing network + */ +function openRemoveVswitchVlanDialog(networkList) { + var names = ''; + for (var i in networkList) { + var networkArgs = networkList[i].split(';'); + networkArgs[2] = jQuery.trim(networkArgs[2]); + names += networkArgs[2] + ', '; + } + names = names.substring(0, names.length - 2); // Delete last two characters + + var confirmDialog = $('

                  Are you sure you want to remove ' + names + '?

                  '); + confirmDialog.dialog({ + title: "Confirm", + modal: true, + width: 400, + buttons: { + "Ok": function() { + for (var i in networkList) { + var networkArgs = networkList[i].split(';'); + var node = networkArgs[0]; + var type = networkArgs[1]; + var name = jQuery.trim(networkArgs[2]); + var owner = networkArgs[3]; + + if (type.indexOf("VSWITCH") != -1) { + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : node, + args : '--removevswitch;' + name, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + var infoMsg; + + // Create info message + if (jQuery.isArray(data.rsp)) { + infoMsg = ''; + for (var i in data.rsp) { + infoMsg += data.rsp[i] + '
                  '; + } + } else { + infoMsg = data.rsp; + } + + openDialog("info", infoMsg); + } + }); + } else if (type.indexOf("LAN") != -1) { + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : node, + args : '--removevlan;' + name + ';' + owner, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + var infoMsg; + + // Create info message + if (jQuery.isArray(data.rsp)) { + infoMsg = ''; + for (var i in data.rsp) { + infoMsg += data.rsp[i] + '
                  '; + } + } else { + infoMsg = data.rsp; + } + + openDialog("info", infoMsg); + } + }); + } + } + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); +} + +/** + * Remove processor + * + * @param node Node where processor is attached + * @param address Virtual address of processor + */ +function removeProcessor(node, address) { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--removeprocessor;' + address, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + $('#' + node + 'StatusBarLoader').show(); + $('#' + node + 'StatusBar').show(); +} + +/** + * Remove disk + * + * @param node Node where disk is attached + * @param address Virtual address of disk + */ +function removeDisk(node, address) { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--removedisk;' + address, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + $('#' + node + 'StatusBarLoader').show(); + $('#' + node + 'StatusBar').show(); +} + +/** + * Remove zFCP device + * + * @param node Node where disk is attached + * @param address Virtual address of zFCP device + * @param wwpn World wide port name of zFCP device + * @param lun Logical unit number of zFCP device + */ +function removeZfcp(node, address, wwpn, lun) { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--removezfcp||' + address + '||' + wwpn + '||' + lun, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + $('#' + node + 'StatusBarLoader').show(); + $('#' + node + 'StatusBar').show(); +} + +/** + * Remove NIC + * + * @param node Node where NIC is attached + * @param address Virtual address of NIC + */ +function removeNic(node, nic) { + var args = nic.split('.'); + var address = args[0]; + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--removenic;' + address, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + + // Increment node process + incrementNodeProcess(node); + + // Show loader + $('#' + node + 'StatusBarLoader').show(); + $('#' + node + 'StatusBar').show(); +} + +/** + * Set a cookie for the network names of a given node + * + * @param data Data from HTTP request + */ +function setNetworkCookies(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var node = data.msg; + var networks = data.rsp[0].split(node + ': '); + + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); + $.cookie('xcat_' + node + 'networks', networks, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Get contents of each disk pool + * + * @param data HTTP request data + */ +function getDiskPool(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Invalid") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var hcp = data.msg; + var pools = data.rsp[0].split(hcp + ': '); + + // Get contents of each disk pool + for (var i in pools) { + if (pools[i]) { + pools[i] = jQuery.trim(pools[i]); + + // Get used space + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcp, + args : '--diskpool;' + pools[i] + ';used', + msg : 'hcp=' + hcp + ';pool=' + pools[i] + ';stat=used' + }, + + success : function(data) { + data = decodeRsp(data); + loadDiskPoolTable(data); + } + }); + + // Get free space + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcp, + args : '--diskpool;' + pools[i] + ';free', + msg : 'hcp=' + hcp + ';pool=' + pools[i] + ';stat=free' + }, + + success : function(data) { + data = decodeRsp(data); + loadDiskPoolTable(data); + } + }); + } // End of if + } // End of for + } else { + // Display any errors in info bar + if (data.rsp.length) { + var panelId = 'zvmDiskResource'; + var info = $('#' + panelId).find('.ui-state-highlight'); + // If there is no info bar, create info bar + if (!info.length) { + info = createInfoBar("Error: "+data.rsp[0]); + $('#' + panelId).append(info); + } else { + info.append("
                  Error: "+data.rsp[0]); + } + } + // Load empty table + loadDiskPoolTable(""); // Must pass something + } +} + +/** + * Get contents of each zFCP pool + * + * @param data HTTP request data + */ +function getZfcpPool(data) { + if (typeof console == "object"){ + console.log("Entering getZfcpPool."); + } + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Invalid") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var hcp = data.msg; + var pools = data.rsp[0].split(hcp + ': '); + zhcpQueryCountForZfcps = 0; + // Get contents of each disk pool + for (var i in pools) { + pools[i] = jQuery.trim(pools[i]); + if (pools[i]) { + + // Query used and free space + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcp, + args : '--zfcppool;' + pools[i] + ';all', + msg : 'hcp=' + hcp + ';pool=' + pools[i] + }, + success : function(data) { + data = decodeRsp(data); + loadZfcpPoolTable(data); + } + }); + } // End of if + } // End of for + } else { + // Display any errors in info bar + if (data.rsp.length) { + var panelId = 'zfcpResource'; + var info = $('#' + panelId).find('.ui-state-highlight'); + // If there is no info bar, create info bar + if (!info.length) { + info = createInfoBar("Error: "+data.rsp[0]); + $('#' + panelId).append(info); + } else { + info.append("
                  Error: "+data.rsp[0]); + } + } + // Load empty table + loadZfcpPoolTable(""); // Must pass something + } +} + +/** + * Get details of each network + * + * @param data HTTP request data + */ +function getNetwork(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Invalid") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var hcp = data.msg; + var networks = data.rsp[0].split(hcp + ': '); + if (typeof console == "object"){ + console.log("Entering getNetwork data:<"+networks+">"); + } + + // Loop through each network + for ( var i = 1; i < networks.length; i++) { + if( !networks[i] || 0 === networks[i].length) continue; + var args = networks[i].split(' '); + var type = args[0]; + var name = args[2]; + name = name.replace(/\n/g,''); + + // Get network details + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcp, + args : '--getnetwork;' + name + ';' + type, + msg : 'hcp=' + hcp + ';type=' + type + ';network=' + name + }, + + success : function(data) { + data = decodeRsp(data); + loadNetworkTable(data); + } + }); + } // End of for + } // End of if + else { + if (data.rsp.length) { + var panelId = 'zvmNetworkResource'; + var info = $('#' + panelId).find('.ui-state-highlight'); + // If there is no info bar, create info bar + if (!info.length) { + info = createInfoBar("Error: "+data.rsp[0]); + $('#' + panelId).append(info); + } else { + info.append("
                  Error: "+data.rsp[0]); + } + } + // Normally load empty table, but not for networks + } +} + +/** + * Load disk pool contents into a table + * + * @param data HTTP request data + */ +function loadDiskPoolTable(data) { + // Remove loader if all hcps queried + var panelId = 'zvmDiskResource'; + if (!zhcpQueryCountForDisks) { + $('#' + panelId).find('img[src="images/loader.gif"]').remove(); + } + + var hcp2zvm = new Object(); + var args, hcp, pool, stat, tmp; + if (data && typeof data.rsp != "undefined") { + // Do not continue if the call failed + if (!data.rsp.length && data.rsp[0].indexOf("Failed") > 0 && data.rsp[0].indexOf("Error") > 0) { + return; + } + + // Obtain mapping for zHCP to zVM system + hcp2zvm = getHcpZvmHash(); + + args = data.msg.split(';'); + hcp = args[0].replace('hcp=', ''); + pool = args[1].replace('pool=', ''); + stat = jQuery.trim(args[2].replace('stat=', '')); + tmp = data.rsp[0].split(hcp + ': '); + } else { + // Provide empty values so the table will be generated + hcp = ''; + pool = ''; + stat = ''; + tmp = new Array(); + } + + // Resource tab ID + var info = $('#' + panelId).find('.ui-state-highlight'); + // If there is no info bar + if (!info.length) { + // Create info bar + info = createInfoBar('Below are disks that are defined in the EXTENT CONTROL file.'); + $('#' + panelId).append(info); + } + + // Get datatable + var tableId = 'zDiskDataTable'; + var dTable = getDiskDataTable(); + if (!dTable) { + // Create a datatable + var table = new DataTable(tableId); + // Resource headers: volume ID, device type, start address, and size + table.init( [ '', 'z/VM', 'Pool', 'Status', 'Volume', 'Device type', 'Starting address', 'Size' ]); + + // Append datatable to panel + $('#' + panelId).append(table.object()); + + // Turn into datatable + dTable = $('#' + tableId).dataTable({ + 'iDisplayLength': 50, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + setDiskDataTable(dTable); + } + + // Skip index 0 and 1 because it contains nothing + for (var i = 2; i < tmp.length; i++) { + tmp[i] = jQuery.trim(tmp[i]); + var diskAttrs = tmp[i].split(' '); + var key = hcp2zvm[hcp] + "-" + pool + "-" + diskAttrs[0]; + var type = diskAttrs[1]; + + // Calculate disk size + var size; + if (type.indexOf('3390') != -1) { + size = convertCylinders2Gb(parseInt(diskAttrs[3])); + } else if (type.indexOf('9336') != -1) { + size = convertBlocks2Gb(parseInt(diskAttrs[3])) + } else { + size = 0; + } + dTable.fnAddData( [ '', hcp2zvm[hcp], pool, stat, diskAttrs[0], type, diskAttrs[2], diskAttrs[3] + " (" + size + "G)" ]); + } + + // Create actions menu + if (!$('#zvmDiskResourceActions').length) { + // Empty filter area + $('#' + tableId + '_length').empty(); + + // Add disk to pool + var addLnk = $('Add'); + addLnk.bind('click', function(event){ + openAddDisk2PoolDialog(); + }); + + // Delete disk from pool + var removeLnk = $('Remove'); + removeLnk.bind('click', function(event){ + var disks = getNodesChecked(tableId); + openRemoveDiskFromPoolDialog(disks); + }); + + // Refresh table + var refreshLnk = $('Refresh'); + refreshLnk.bind('click', function(event){ + $('#zvmDiskResource').empty().append(createLoader('')); + setDiskDataTable(''); + + // Create a array for hardware control points + var hcps = new Array(); + if ($.cookie('xcat_hcp').indexOf(',') > -1) + hcps = $.cookie('xcat_hcp').split(','); + else + hcps.push($.cookie('xcat_hcp')); + + zhcpQueryCountForDisks = hcps.length; + // Query the disk pools for each + for (var i in hcps) { + if( !hcps[i] || 0 === hcps[i].length) continue; + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcps[i], + args : '--diskpoolnames', + msg : hcps[i] + }, + + success : function(data) { + data = decodeRsp(data); + getDiskPool(data); + } + }); + zhcpQueryCountForDisks--; + } + }); + + // Add ECKD to system + var addEckdLnk = $('Add ECKD'); + addEckdLnk.bind('click', function(event){ + openAddEckd2SystemDialog(hcp); + }); + + // Add Page or Spool + var addPageSpoolLnk = $('Add page/spool') + addPageSpoolLnk.bind('click', function(event){ + openAddPageSpoolDialog(hcp); + }); + + // Add EDEV to system + var addEdevLnk = $('Add EDEV'); + addEdevLnk.bind('click', function(event){ + openAddScsi2SystemDialog(hcp); + }); + + // Remove EDEV + var removeEdevLnk = $('Remove EDEV'); + removeEdevLnk.bind('click', function(event){ + openRemoveScsiDialog(hcp); + }); + + // Indicate disk is to be shared with various users + var shareLnk = $('Share disk'); + shareLnk.bind('click', function(event){ + var disks = getNodesChecked(tableId); + openShareDiskDialog(disks); + }); + + // Add Volume to system + var addVolumeLnk = $('Add volume to system'); + addVolumeLnk.bind('click', function(event){ + openAddVolume2SystemDialog(hcp); + }); + + // Remove Volume from system + var removeVolumeLnk = $('Remove volume from system'); + removeVolumeLnk.bind('click', function(event){ + openRemoveVolumeFromSystemDialog(hcp); + }); + + // Advanced menu + var advancedLnk = 'Advanced'; + var advancedMenu = createMenu([addEckdLnk, addPageSpoolLnk, addEdevLnk, removeEdevLnk, addVolumeLnk, removeVolumeLnk, shareLnk]); + + // Create action bar + var actionBar = $('
                  ').css("width", "450px"); + + // Create an action menu + var actionsMenu = createMenu([refreshLnk, addLnk, removeLnk, [advancedLnk, advancedMenu]]); + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); + $('#' + tableId + '_length').prepend(menuDiv); + $('#' + tableId + '_length').css({ + 'padding': '0px', + 'width': '500px' + }); + $('#' + tableId + '_filter').css('padding', '10px'); + menuDiv.append(actionBar); + } + + // Resize accordion + $('#zvmResourceAccordion').accordion('resize'); +} + +/** + * Load zFCP pool contents into a table + * + * @param data HTTP request data + */ +function loadZfcpPoolTable(data) { + if (typeof console == "object"){ + console.log("Entering loadZfcpPoolTable."); + } + // Delete loader if last one + var panelId = 'zfcpResource'; + if (zhcpQueryCountForZfcps <= 0) { + $('#' + panelId).find('img[src="images/loader.gif"]').remove(); + } + + var hcp2zvm = new Object(); + var args, hcp, pool, tmp; + + // Resource tab ID + var info = $('#' + panelId).find('.ui-state-highlight'); + + // Is there any data passed? Process if some + if (typeof data.rsp != "undefined") { + // Do not continue if no data to add + if (!data.rsp.length) { + if (typeof console == "object"){ + console.log("data.rsp.length is 0."); + } + // If there is no info bar, create info bar + var msgError = '
                  Unexpected, no data returned on the lsvm --zfcppool call.'; + if (!info.length) { + info = createInfoBar(msgError); + $('#' + panelId).append(info); + } else { + info.append(msgError); + } + return; + } + if (data.rsp[0].indexOf("Failed") > 0 || data.rsp[0].indexOf("Error") > 0) { + if (typeof console == "object"){ + console.log("Failed on lsvm call for --zfcppool"); + } + var msgError = '
                  Error: Error on call to check zfcp pools: '+ data.rsp[0]; + // If there is no info bar, create info bar + if (!info.length) { + info = createInfoBar(msgError); + $('#' + panelId).append(info); + } else { + info.append(msgError); + } + return; + } + + // Obtain mapping for zHCP to zVM system + hcp2zvm = getHcpZvmHash(); + + args = data.msg.split(';'); + hcp = args[0].replace('hcp=', ''); + pool = args[1].replace('pool=', ''); + tmp = data.rsp[0].split(hcp + ': '); + } else { + // Provide empty values so the table will be generated + if (typeof console == "object"){ + console.log("Creating empty zfcp pool table."); + } + hcp = ''; + pool = '' + tmp = new Array(); + } + + // If there is no info bar, create info bar + if (!info.length) { + info = createInfoBar('Below are devices that are defined internally in the zFCP pools.'); + $('#' + panelId).append(info); + } + + // Get datatable + var tableId = 'zFcpDataTable'; + var dTable = getZfcpDataTable(); + if (!dTable) { + // Create a datatable + var table = new DataTable(tableId); + // Resource headers: status, WWPN, LUN, size, owner, channel, tag + table.init( [ '', 'z/VM', 'Pool', 'Status', 'Port name', 'Unit number', 'Size', 'Range', 'Owner', 'Channel', 'Tag' ]); + + // Append datatable to panel + $('#' + panelId).append(table.object()); + + // Turn into datatable + dTable = $('#' + tableId).dataTable({ + 'iDisplayLength': 50, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + setZfcpDataTable(dTable); + } + if ((typeof data.rsp != "undefined") && (data.rsp.length > 0)) { + // Skip index 0 and 1 because it contains nothing + var key = ""; + for (var i = 2; i < tmp.length; i++) { + tmp[i] = jQuery.trim(tmp[i]); + var diskAttrs = tmp[i].split(','); + diskAttrs[0] = diskAttrs[0].toLowerCase(); + // Key contains row data to be returned when the checkbox is selected + var key = hcp2zvm[hcp] + '-' + pool + '-' + diskAttrs[2] + '-' + diskAttrs[1]; + dTable.fnAddData( [ '', hcp2zvm[hcp], pool, diskAttrs[0], diskAttrs[1], diskAttrs[2], diskAttrs[3], diskAttrs[4], diskAttrs[5], diskAttrs[6], diskAttrs[7] ]); + } + } + // Create actions menu + if (!$('#zFcpResourceActions').length) { + // Empty filter area + $('#' + tableId + '_length').empty(); + + // Add disk to pool + var addLnk = $('Add'); + addLnk.bind('click', function(event){ + openAddZfcp2PoolDialog(); + }); + + // Delete disk from pool + var removeLnk = $('Remove'); + removeLnk.bind('click', function(event){ + if (typeof console == "object"){ + console.log("Remove button clicked for tableId:"+tableId); + } + var disks = getNodesChecked(tableId); + openRemoveZfcpFromPoolDialog(disks); + }); + + // Refresh table + var refreshLnk = $('Refresh'); + refreshLnk.bind('click', function(event){ + $('#zfcpResource').empty().append(createLoader('')); + setZfcpDataTable(''); + + // Create a array for hardware control points + var hcps = new Array(); + if ($.cookie('xcat_hcp').indexOf(',') > -1) + hcps = $.cookie('xcat_hcp').split(','); + else + hcps.push($.cookie('xcat_hcp')); + + // Query the disk pools for each + zhcpQueryCountForZfcps = hcps.length; + for (var i in hcps) { + if( !hcps[i] || 0 === hcps[i].length) continue; + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcps[i], + args : '--zfcppoolnames', + msg : hcps[i] + }, + + success : function(data) { + data = decodeRsp(data); + getZfcpPool(data); + } + }); + zhcpQueryCountForZfcps--; + } + }); + // Create action bar + var actionBar = $('
                  ').css("width", "450px"); + + // Create an action menu + var actionsMenu = createMenu([addLnk, removeLnk, refreshLnk]); + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); + $('#' + tableId + '_length').prepend(menuDiv); + $('#' + tableId + '_length').css({ + 'padding': '0px', + 'width': '500px' + }); + $('#' + tableId + '_filter').css('padding', '10px'); + menuDiv.append(actionBar); + } + + // Resize accordion + $('#zvmResourceAccordion').accordion('resize'); +} + +/** + * Open dialog to remove disk from pool + * + * @param disks2remove Disks selected in table + */ +function openRemoveDiskFromPoolDialog(disks2remove) { + // Create form to delete disk from pool + var dialogId = 'zvmDeleteDiskFromPool'; + var deleteDiskForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + var disks = new Array(); + if (disks2remove.indexOf(',') > -1) + disks = disks2remove.split(','); + else + disks.push(disks2remove); + + // Pick the last zHCP and pool it finds + var args, tgtHcp = "", tgtPool = "", tgtVol = ""; + for (var i in disks) { + if( !disks[i] || 0 === disks[i].length) continue; + args = disks[i].split('-'); + tgtHcp = args[0]; + tgtPool = args[1]; + tgtVol += args[2] + ','; + } + + // Strip out last comma + tgtVol = tgtVol.slice(0, -1); + + // Create info bar + var info = createInfoBar('Remove a disk from a disk pool defined in the EXTENT CONTROL.'); + deleteDiskForm.append(info); + var action = $('
                  '); + var actionSelect = $(''); + action.append(actionSelect); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + // Set region input based on those selected on table (if any) + var region = $('
                  '); + var group = $('
                  '); + deleteDiskForm.append(action, system, region, group); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + systemSelect.val(tgtHcp); + + actionSelect.change(function() { + if ($(this).val() == '1' || $(this).val() == '3') { + region.show(); + group.hide(); + } else if ($(this).val() == '2') { + region.show(); + group.show(); + } else if ($(this).val() == '7') { + region.val('FOOBAR'); + region.hide(); + group.show(); + } + }); + + // Generate tooltips + deleteDiskForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to delete disk + deleteDiskForm.dialog({ + title:'Delete disk from pool', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 500, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var action = $(this).find('select[name=action]').val(); + var system = $(this).find('select[name=system]').val(); + var region = $(this).find('input[name=region]').val(); + var group = $(this).find('input[name=group]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'select[name=action]', 'input[name=region]', 'input[name=group]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + var args; + if (action == '2' || action == '7') + args = region + ';' + group; + else + args = region; + + // Remove disk from pool + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : '--removediskfrompool;' + action + ';' + args, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Open dialog to add disk to pool + */ +function openAddDisk2PoolDialog() { + // Create form to add disk to pool + var dialogId = 'zvmAddDisk2Pool'; + var addDiskForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + // Create info bar + var info = createInfoBar('Add a disk to a disk pool defined in the EXTENT CONTROL. The disk has to already be attached to SYSTEM.'); + addDiskForm.append(info); + var action = $('
                  '); + var actionSelect = $(''); + action.append(actionSelect); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + var volume = $('
                  '); + var group = $('
                  '); + addDiskForm.append(action, system, volume, group); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + // Generate tooltips + addDiskForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add disk + addDiskForm.dialog({ + title:'Add disk to pool', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 500, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get inputs + var action = $(this).find('select[name=action]').val(); + var system = $(this).find('select[name=system]').val(); + var volume = $(this).find('input[name=volume]').val(); + var group = $(this).find('input[name=group]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'select[name=action]', 'input[name=volume]', 'input[name=group]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + var args; + if (action == '4') + args = volume + ';' + volume + ';' + group; + else + args = volume + ';' + group; + + // Add disk to pool + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : '--adddisk2pool;' + action + ';' + args, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Open dialog to remove zFCP from pool + * + * @param devices2remove Comman separated devices selected in table + */ +function openRemoveZfcpFromPoolDialog(devices2remove) { + // Create form to delete device from pool + var dialogId = 'zvmDeleteZfcpFromPool'; + var deleteDiskForm = $('
                  '); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + // Verify disks are in the same zFCP pool + var devices = devices2remove.split(','); + if (typeof console == "object"){ + console.log("Entering openRemoveZfcpFromPoolDialog. Device to remove:<"+devices2remove+">"); + } + var tmp, tgtPool, tgtHcp; + var tgtPort = ""; + var tgtUnitNo = ""; + for (var i in devices) { + if( !devices[i] || 0 === devices[i].length) continue; + tmp = devices[i].split('-'); + + if (tgtPool && tmp[1] != tgtPool) { + openDialog("warn", "Please select devices in the same zFCP"); + return; + } else { + tgtPool = tmp[1]; + } + + tgtHcp = tmp[0]; // Assume it is just one zHCP. Otherwise, this cannot be done on multiple zHCPs. + tgtUnitNo += tmp[2] + ","; + tgtPort = tmp[3]; + } + + // Strip out last comma + tgtUnitNo = tgtUnitNo.slice(0, -1); + + // Create info bar + var info = createInfoBar('Remove a zFCP device that is defined in a zFCP pool.'); + deleteDiskForm.append(info); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + var pool = $('
                  '); + var unitNo = $('
                  '); + var portName = $('
                  '); + deleteDiskForm.append(system, pool, unitNo, portName); + + // Append options for hardware control points + //systemSelect.append($('')); + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + systemSelect.val(tgtHcp); + + // Generate tooltips + deleteDiskForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to delete device + deleteDiskForm.dialog({ + title:'Delete device from pool', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 500, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var system = $(this).find('select[name=system]').val(); + var pool = $(this).find('input[name=zfcpPool]').val(); + var unitNo = $(this).find('input[name=zfcpUnitNo]').val(); + var portName = $(this).find('input[name=zfcpPortName]').val(); + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=zfcpPool]', 'input[name=zfcpUnitNo]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + var args = '--removezfcpfrompool;' + pool + ';' + unitNo; + if (portName) { + args += ';' + portName; + } + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : system, + args : args, + msg : dialogId + }, + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Open dialog to add zFCP to pool + */ +function openAddZfcp2PoolDialog() { + // Create form to add disk to pool + var dialogId = 'zvmAddDisk2Pool'; + var addDiskForm = $('
                  '); + var info = createInfoBar('Add a device to a zFCP pool defined in xCAT.'); + addDiskForm.append(info); + + // Obtain mapping for zHCP to zVM system + var hcp2zvm = new Object(); + hcp2zvm = getHcpZvmHash(); + + var system = $('
                  '); + var systemSelect = $(''); + system.append(systemSelect); + + var pool = $('
                  '); + var status = $('
                  '); + var portName = $('
                  '); + var unitNo = $('
                  '); + var size = $('
                  '); + var range = $('
                  '); + var owner = $('
                  '); + addDiskForm.append(system, pool, status, portName, unitNo, size, range, owner); + + // Create a array for hardware control points + //systemSelect.append($('')); + // Append options for hardware control points + for (var hcp in hcp2zvm) { + systemSelect.append($('')); + } + + // Generate tooltips + addDiskForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add disk + addDiskForm.dialog({ + title:'Add device to pool', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 500, + buttons: { + "Ok": function(){ + // Delete any warning messages + $(this).find('.ui-state-error').remove(); + + var tgtSystem = $(this).find('select[name=system]').val(); + var tgtPool = $(this).find('input[name=zfcpPool]').val(); + var tgtStatus = $(this).find('select[name=zfcpStatus]').val(); + var tgtPortName = $(this).find('input[name=zfcpPortName]').val(); + var tgtUnitNo = $(this).find('input[name=zfcpUnitNo]').val(); + var tgtSize = $(this).find('input[name=zfcpSize]').val(); + var tgtRange = $(this).find('input[name=zfcpRange]').val(); + + // Device owner is optional + var tgtOwner = ""; + if ($(this).find('input[name=zfcpOwner]').val()) { + tgtOwner = $(this).find('input[name=zfcpOwner]').val(); + } + + // If inputs are not complete, show warning message + var ready = true; + var args = new Array('select[name=system]', 'input[name=zfcpPool]', 'select[name=zfcpStatus]', 'input[name=zfcpPortName]', 'input[name=zfcpUnitNo]'); + for (var i in args) { + if (!$(this).find(args[i]).val()) { + $(this).find(args[i]).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + $(this).find(args[i]).css('border', 'solid #BDBDBD 1px'); + } + } + + if (!ready) { + // Show warning message + var warn = createWarnBar('Please provide a value for each required field.'); + warn.prependTo($(this)); + return; + } + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + // zFCP range and owner are optional + var args = '--addzfcp2pool||' + tgtPool + '||' + tgtStatus + '||"' + tgtPortName + '"||' + tgtUnitNo + '||' + tgtSize; + if (tgtRange) { + args += '||' + tgtRange; + } if (tgtOwner) { + args += '||' + tgtOwner; + } + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chhypervisor', + tgt : tgtSystem, + args : args, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateResourceDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Update resource dialog + * + * @param data HTTP request data + */ +function updateResourceDialog(data) { + var dialogId = data.msg; + var infoMsg; + + // Create info message + if (jQuery.isArray(data.rsp)) { + infoMsg = ''; + for (var i in data.rsp) { + infoMsg += data.rsp[i] + '
                  '; + } + } else { + infoMsg = data.rsp; + } + + // Create info bar with close button + var infoBar = $('
                  ').css('margin', '5px 0px'); + var icon = $('').css({ + 'display': 'inline-block', + 'margin': '10px 5px' + }); + + // Create close button to close info bar + var close = $('').css({ + 'display': 'inline-block', + 'float': 'right' + }).click(function() { + $(this).parent().remove(); + }); + + var msg = $('
                  ' + infoMsg + '
                  ').css({ + 'display': 'inline-block', + 'width': '90%' + }); + + infoBar.append(icon, msg, close); + infoBar.prependTo($('#' + dialogId)); +} + +/** + * Select all checkboxes in the datatable + * + * @param event Event on element + * @param obj Object triggering event + */ +function selectAllDisk(event, obj) { + // This will ascend from + var tableObj = obj.parents('.datatable'); + var status = obj.attr('checked'); + tableObj.find(' :checkbox').attr('checked', status); + + // Handle datatable scroll + tableObj = obj.parents('.dataTables_scroll'); + if (tableObj.length) { + tableObj.find(' :checkbox').attr('checked', status); + } + + event.stopPropagation(); +} + +/** + * Load network details into a table + * + * @param data HTTP request data + */ +function loadNetworkTable(data) { + // Remove loader if last one + var panelId = 'zvmNetworkResource'; + if (!zhcpQueryCountForNetworks) { + $('#' + panelId).find('img[src="images/loader.gif"]').remove(); + } + + // Get zVM host names + if (!$.cookie('xcat_zvms')) { + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + async: false, + data : { + cmd : 'webportal', + tgt : '', + args : 'lszvm', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setzVMCookies(data); + } + }); + } + + var zvms = $.cookie('xcat_zvms').split(','); + var hcp2zvm = new Object(); + var args, zvm, iHcp, tmp; + for (var i in zvms) { + if( !zvms[i] || 0 === zvms[i].length) continue; + args = zvms[i].split(':'); + zvm = args[0].toLowerCase(); + + if (args[1].indexOf('.') != -1) { + tmp = args[1].split('.'); + iHcp = tmp[0]; + } else { + iHcp = args[1]; + } + + hcp2zvm[iHcp] = zvm; + } + + var args = data.msg.split(';'); + var hcp = args[0].replace('hcp=', ''); + var type = args[1].replace('type=', ''); + var name = jQuery.trim(args[2].replace('network=', '')); + tmp = data.rsp[0].split(hcp + ': '); + + // Resource tab ID + var info = $('#' + panelId).find('.ui-state-highlight'); + // If there is no info bar + if (!info.length) { + // Create info bar + info = createInfoBar('Below are LANs/VSWITCHes available to use.'); + $('#' + panelId).append(info); + } + + // Get datatable + var dTable = getNetworkDataTable(); + if (!dTable) { + // Create table + var tableId = 'zNetworkDataTable'; + var table = new DataTable(tableId); + table.init( [ '', 'z/VM', 'Type', 'Name', 'Layer', 'Owner', 'Controller', 'Details' ]); + + // Append datatable to tab + $('#' + panelId).append(table.object()); + + // Turn into datatable + dTable = $('#' + tableId).dataTable({ + 'iDisplayLength': 50, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + setNetworkDataTable(dTable); + + // Set the column width + var cols = table.object().find('thead tr th'); + cols.eq(0).css('width', '20px'); // HCP column + cols.eq(1).css('width', '20px'); // Type column + cols.eq(2).css('width', '20px'); // Name column + cols.eq(3).css({'width': '600px'}); // Details column + } + + // Skip index 0 because it contains nothing + var details = '
                  ';
                  +    for ( var i = 1; i < tmp.length; i++) {
                  +        details += tmp[i];
                  +    }
                  +    details += '
                  '; + + // Determine the OSI layer + var layer = "3"; + if (details.indexOf("ETHERNET") != -1) { + layer = "2"; + } + + // Find the vSwitch/VLAN owner + var regex = /(LAN|VSWITCH) (.*?)(?:\s|$)/g; + var owner = ""; + var match = ""; + if (type == "VSWITCH") { + owner = "SYSTEM"; + } else { + owner = regex.exec(details)[2]; + } + + // Find the vSwitch controller + regex = /(?:^|\s)Controller: (.*?)(?:\s|$)/g; + var controllers = ""; + match = ""; + while (match = regex.exec(details)) { + controllers += match[1] + ","; + } + controllers = controllers.substring(0, controllers.length - 1); // Delete last two characters + + dTable.fnAddData(['', '
                  ' + hcp2zvm[hcp] + '
                  ', '
                  ' + type + '
                  ', '
                  ' + name + '
                  ', '
                  ' + layer + '
                  ', '
                  ' + owner + '
                  ', '
                  ' + controllers + '
                  ', details]); + + // Create actions menu + if (!$('#networkResourceActions').length) { + // Empty filter area + $('#' + tableId + '_length').empty(); + + // Add Vswitch/Vlan + var addLnk = $('Add'); + addLnk.bind('click', function(event){ + openAddVswitchVlanDialog(); + }); + + // Remove Vswitch/Vlan + var removeLnk = $('Remove'); + removeLnk.bind('click', function(event){ + var networkList = getNodesChecked(tableId).split(','); + if (networkList) { + openRemoveVswitchVlanDialog(networkList); + } + }); + + // Refresh table + var refreshLnk = $('Refresh'); + refreshLnk.bind('click', function(event){ + $('#zvmNetworkResource').empty().append(createLoader('')); + setNetworkDataTable(''); + + // Create a array for hardware control points + var hcps = new Array(); + if ($.cookie('xcat_hcp').indexOf(',') > -1) + hcps = $.cookie('xcat_hcp').split(','); + else + hcps.push($.cookie('xcat_hcp')); + + // Query networks + zhcpQueryCountForNetworks = hcps.length; + for (var i in hcps) { + if( !hcps[i] || 0 === hcps[i].length) continue; + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : hcps[i], + args : '--getnetworknames', + msg : hcps[i] + }, + + success : function(data) { + data = decodeRsp(data); + getNetwork(data); + } + }); + zhcpQueryCountForNetworks--; + } + }); + + // Create action bar + var actionBar = $('
                  ').css("width", "450px"); + + // Create an action menu + var actionsMenu = createMenu([addLnk, removeLnk, refreshLnk]); + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); + $('#' + tableId + '_length').prepend(menuDiv); + $('#' + tableId + '_length').css({ + 'padding': '0px', + 'width': '500px' + }); + $('#' + tableId + '_filter').css('padding', '10px'); + menuDiv.append(actionBar); + } + + // Resize accordion + $('#zvmResourceAccordion').accordion('resize'); +} + +/** + * Connect a NIC to a Guest LAN + * + * @param data Data from HTTP request + */ +function connect2GuestLan(data) { + var rsp = data.rsp; + var args = data.msg.split(';'); + var node = args[0].replace('node=', ''); + var address = args[1].replace('addr=', ''); + var lanName = args[2].replace('lan=', ''); + var lanOwner = args[3].replace('owner=', ''); + + // Write ajax response to status bar + var prg = writeRsp(rsp, node + ': '); + $('#' + node + 'StatusBar').find('div').append(prg); + + // Continue if no errors found + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + // Connect NIC to Guest LAN + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--connectnic2guestlan;' + address + ';' + lanName + ';' + + lanOwner, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + } else { + // Hide loader when error + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).hide(); + } +} + +/** + * Connect a NIC to a VSwitch + * + * @param data Data from HTTP request + */ +function connect2VSwitch(data) { + var rsp = data.rsp; + var args = data.msg.split(';'); + var node = args[0].replace('node=', ''); + var address = args[1].replace('addr=', ''); + var vswitchName = args[2].replace('vsw=', ''); + var vswitchAware = args[3].replace('vlanaware=', ''); + var vswitchPortType = args[4].replace('porttype=', ''); + var vswitchLanId = args[5].replace('lanid=', ''); + + // Set variables to empty string if notaware or they contain "default" + if (vswitchAware.toLowerCase() == 'notaware' ) { + vswitchPortType = ''; + vswitchLanId = ''; + } else { + if (vswitchPortType.toLowerCase() == 'default' ) { + vswitchPortType = ''; + } + if (vswitchLanId.toLowerCase() == 'default' ) { + vswitchLanId = ''; + } + } + + // Write ajax response to status bar + var prg = writeRsp(rsp, node + ': '); + $('#' + node + 'StatusBar').find('div').append(prg); + + // Continue if no errors found + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + // Connect NIC to VSwitch + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chvm', + tgt : node, + args : '--connectnic2vswitch;' + address + ';' + vswitchName + ';' + + vswitchPortType + ';' + vswitchLanId, + msg : node + }, + + success : function(data) { + data = decodeRsp(data); + updateZNodeStatus(data); + } + }); + } else { + // Hide loader when error + var statusBarLoaderId = node + 'StatusBarLoader'; + $('#' + statusBarLoaderId).hide(); + } +} + +/** + * Create provision existing node division + * + * @param inst Provision tab instance + * @return Provision existing node division + */ +function createZProvisionExisting(inst) { + // Create provision existing and hide it + var provExisting = $('
                  ').hide(); + + var vmFS = $('
                  '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + provExisting.append(vmFS); + + var vmAttr = $('
                  '); + vmFS.append($('
                  ')); + vmFS.append(vmAttr); + + var osFS = $('
                  '); + var osLegend = $('Operating System'); + osFS.append(osLegend); + provExisting.append(osFS); + + var osAttr = $('
                  '); + osFS.append($('
                  ')); + osFS.append(osAttr); + + // Create group input + var group = $('
                  '); + var groupLabel = $(''); + group.append(groupLabel); + + // Turn on auto complete for group + var groupNames = $.cookie('xcat_groups'); + if (groupNames) { + // Split group names into an array + var tmp = groupNames.split(','); + + // Create drop down for groups + var groupSelect = $(''); + groupSelect.append(''); + for (var i in tmp) { + if( !tmp[i] || 0 === tmp[i].length) continue; + // Add group into drop down + var opt = $(''); + groupSelect.append(opt); + } + group.append(groupSelect); + + // Create node datatable + groupSelect.change(function(){ + // Get group selected + var thisGroup = $(this).val(); + // If a valid group is selected + if (thisGroup) { + createNodesDatatable(thisGroup, 'zNodesDatatableDIV' + inst); + } + }); + } else { + // If no groups are cookied + var groupInput = $(''); + group.append(groupInput); + } + vmAttr.append(group); + + // Create node input + var node = $('
                  '); + var nodeLabel = $(''); + var nodeDatatable = $('

                  Select a group to view its nodes

                  '); + node.append(nodeLabel); + node.append(nodeDatatable); + vmAttr.append(node); + + // Create operating system image input + var os = $('
                  '); + var osLabel = $(''); + var osSelect = $(''); + osSelect.append($('')); + + var imageNames = $.cookie('xcat_imagenames').split(','); + if (imageNames) { + imageNames.sort(); + for (var i in imageNames) { + if( !imageNames[i] || 0 === imageNames[i].length) continue; + osSelect.append($('')); + } + } + os.append(osLabel); + os.append(osSelect); + osAttr.append(os); + + // Create boot method drop down + var bootMethod = $('
                  '); + var methoddLabel = $(''); + var methodSelect = $(''); + methodSelect.append('' + + '' + + '' + + '' + + '' + ); + bootMethod.append(methoddLabel); + bootMethod.append(methodSelect); + osAttr.append(bootMethod); + + // Generate tooltips + provExisting.find('div input[title],select[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" + } + }); + + /** + * Provision existing + */ + var provisionBtn = createButton('Provision'); + provisionBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parent().parent().find('.ui-state-error').remove(); + + var ready = true; + var errMsg = ''; + + // Get provision tab ID + var thisTabId = $(this).parent().parent().parent().attr('id'); + // Get provision tab instance + var inst = thisTabId.replace('zvmProvisionTab', ''); + + // Get nodes that were checked + var dTableId = 'zNodesDatatable' + inst; + var tgts = getNodesChecked(dTableId); + if (!tgts) { + errMsg += 'You need to select a node.
                  '; + ready = false; + } + + // Check operating system image + var os = $('#' + thisTabId + ' select[name=os]:visible'); + if (!os.val()) { + errMsg += 'You need to select a operating system image.'; + os.css('border', 'solid #FF0000 1px'); + ready = false; + } else { + os.css('border', 'solid #BDBDBD 1px'); + } + + // If all inputs are valid, ready to provision + if (ready) { + // Disable provision button + $(this).attr('disabled', 'true'); + + // Show loader + $('#zProvisionStatBar' + inst).show(); + $('#zProvisionLoader' + inst).show(); + + // Disable all inputs + var inputs = $('#' + thisTabId + ' input:visible'); + inputs.attr('disabled', 'disabled'); + + // Disable all selects + var selects = $('#' + thisTabId + ' select'); + selects.attr('disabled', 'disabled'); + + // Get operating system image + var osImage = $('#' + thisTabId + ' select[name=os]:visible').val(); + var tmp = osImage.split('-'); + var os = tmp[0]; + var arch = tmp[1]; + var profile = tmp[3]; + + /** + * (1) Set operating system + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : tgts + ';noderes.netboot=zvm;nodetype.os=' + os + ';nodetype.arch=' + arch + ';nodetype.profile=' + profile, + msg : 'cmd=nodeadd;out=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionExistingStatus(data); + } + }); + } else { + // Show warning message + var warn = createWarnBar(errMsg); + warn.prependTo($(this).parent().parent()); + } + }); + provExisting.append(provisionBtn); + + return provExisting; +} + +/** + * Create provision new node division + * + * @param inst Provision tab instance + * @return Provision new node division + */ +function createZProvisionNew(inst) { + if (typeof console == "object"){ + console.log("Entering createZProvisionNew. Inst value:"+inst); + } + // Create provision new node division + var provNew = $('
                  '); + + // Create VM fieldset + var vmFS = $('
                  '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + provNew.append(vmFS); + + var vmAttr = $('
                  '); + vmFS.append($('
                  ')); + vmFS.append(vmAttr); + + // Create OS fieldset + var osFS = $('
                  '); + var osLegend = $('Operating System'); + osFS.append(osLegend); + provNew.append(osFS); + + // Create hardware fieldset + var hwFS = $('
                  '); + var hwLegend = $('Hardware'); + hwFS.append(hwLegend); + provNew.append(hwFS); + + var hwAttr = $('
                  '); + hwFS.append($('
                  ')); + hwFS.append(hwAttr); + + // Create tabs for basic and advanced hardware configuration + var hwTab = new Tab('hwConfig' + inst); + hwTab.init(); + hwAttr.append(hwTab.object()); + + var osAttr = $('
                  '); + osFS.append($('
                  ')); + osFS.append(osAttr); + + // Create group input + var group = $('
                  '); + var groupLabel = $(''); + var groupInput = $(''); + // Get groups on-focus + groupInput.one('focus', function(){ + var groupNames = $.cookie('xcat_groups'); + if (groupNames) { + // Turn on auto complete + $(this).autocomplete({ + source: groupNames.split(',') + }); + } + }); + group.append(groupLabel); + group.append(groupInput); + vmAttr.append(group); + + // Create node input + var nodeName = $('
                  '); + var nodeLabel = $(''); + var nodeInput = $(''); + nodeName.append(nodeLabel); + nodeName.append(nodeInput); + vmAttr.append(nodeName); + + // Create user ID input + var userId = $('
                  '); + vmAttr.append(userId); + + // Create hardware control point input + var hcpDiv = $('
                  '); + var hcpNodeLabel = $(''); + var hcpNodeInput = $(''); + var hcpHiddenInput = $(''); + hcpNodeInput.blur(function() { + + if (typeof console == "object") { + console.log("Display loading bar "); + } + // Show the status bar with a message and loading gif + $('#'+'zProvisionStatBar'+inst).find('div').append("Loading zhcp information..."); + $('#'+'zProvisionStatBar'+inst).find('div').append(""); + $('#'+'zProvisionStatBar'+inst).show(); + + // list of calls after the zhcp is verified. Used to determine when in progress gif is to be removed. + var ajaxCalls = {"diskpoolnames":1, "zfcppoolnames":1, "userprofilenames":1}; + var zhcpToCheck = $(this).val(); + var zhcpField = $(this); + var provisionStatusBar = $('#'+'zProvisionStatBar'+inst); + + // Make sure border is set back to black + zhcpField.css('border', 'solid #BDBDBD 1px'); + + if ($(this).val()) { + // Check if this is a valid node by making network names call. + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : zhcpToCheck, + args : '--getnetworknames', + msg : zhcpToCheck + }, + + success : function(data) { + data = decodeRsp(data); + if (data.rsp.length && (data.rsp[0].indexOf("Failed") > -1 || data.rsp[0].indexOf("Invalid") > -1 || data.rsp[0].indexOf("Error") > -1 ) ) { + // Remove the progress gif, since bailing out + removeProvisionLoadingGif(provisionStatusBar); + + // Create warning dialog + var warning = createWarnBar('Failure getting network data for hardware control point ' + zhcpToCheck + '
                  The hcp field must be a xCAT node name.'); + var warnDialog = $('
                  ').append(warning); + + // highlight the hcp field + zhcpField.css('border', 'solid #FF0000 1px'); + + // Open warning dialog + warnDialog.dialog({ + title:'Warning', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function() { + $(this).dialog("close"); + } + } + }); + + } else { + // Node is good, now set some cookies from network, then check/set other cookies + setNetworkCookies(data); + + // Get the HCP name from the hcp node name + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : zhcpToCheck, + msg : 'zhcpFullName' + }, + + success : function(data) { + data = decodeRsp(data); + if (data.rsp.length && (data.rsp[0].indexOf("Failed") > -1 || data.rsp[0].indexOf("Invalid") > -1) ) { + // Remove the progress gif, since bailing out + removeProvisionLoadingGif(provisionStatusBar); + + // Create warning dialog + var warning = createWarnBar('Failure getting hcp data from hardware control point ' + zhcpToCheck + '
                  The hcp field must be a valid xCAT node name.'); + var warnDialog = $('
                  ').append(warning); + + // highlight the hcp field + zhcpField.css('border', 'solid #FF0000 1px'); + + // Open warning dialog + warnDialog.dialog({ + title:'Warning', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function() { + $(this).dialog("close"); + } + } + }); + } else { + // Now set the hidden hcp field with the full name + // Clear hash table containing definable node attributes + nodeAttrs = new Array(); + + // Get definable attributes + // Data returned + var rsp = data.rsp; + // Group name + var group = data.msg; + // Hash of node attributes + var attrs = new Object(); + + // Go through each attribute + var node, args; + for (var i in rsp) { + // Get node name, skip processing + if (rsp[i].indexOf('Object name:') > -1) { + i++; + } + + // Get key and value + args = rsp[i].split('=', 2); + var key = jQuery.trim(args[0]); + var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length)); + + // If this is zhcp key then save full name in hidden field + if (key == "hcp") { + hcpHiddenInput.val(val); + } + + } + + } + } + }); + + if (typeof console == "object"){ + console.log("Looking for cookies from <" + zhcpToCheck + ">"); + } + + if (!$.cookie('xcat_' + zhcpToCheck + 'diskpools')) { + // Get disk pools + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : zhcpToCheck, + args : '--diskpoolnames', + msg : zhcpToCheck + }, + + success : function(data) { + data = decodeRsp(data); + setDiskPoolCookies(data); + }, + complete : function() { + checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "diskpoolnames"); + } + }); + } else { + checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "diskpoolnames"); + } + + if (!$.cookie('xcat_' + zhcpToCheck + 'zfcppools')) { + // Get zFCP pools + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : zhcpToCheck, + args : '--zfcppoolnames', + msg : zhcpToCheck + }, + + success : function(data) { + data = decodeRsp(data); + setZfcpPoolCookies(data); + }, + complete : function() { + checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "zfcppoolnames"); + } + }); + } else { + checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "zfcppoolnames"); + } + + if (!$.cookie('xcat_' + zhcpToCheck + 'userprofiles')) { + // Get zFCP pools + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + async: false, + data : { + cmd : 'lsvm', + tgt : zhcpToCheck, + args : '--userprofilenames', + msg : zhcpToCheck + }, + + success : function(data) { + data = decodeRsp(data); + setUserProfilesCookies(data); + }, + complete : function() { + checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "userprofilenames"); + } + }); + } else { + checkProvisionCallsDone(provisionStatusBar, ajaxCalls, "userprofilenames"); + } + + // Reset user profile and network drop down box + var thisTabId = zhcpField.parents('.tab').attr('id'); + var thisUserProfile = $('#' + thisTabId + ' select[name=userProfile]'); + thisUserProfile.children().remove(); + + var definedUserProfiles = $.cookie('xcat_' + zhcpToCheck + 'userprofiles').split(','); + for (var i in definedUserProfiles) { + if( !definedUserProfiles[i] || 0 === definedUserProfiles[i].length) continue; + thisUserProfile.append(''); + } + + var thisNetwork = $('#' + thisTabId + ' select[name=network]'); + thisNetwork.children().remove(); + thisNetwork.append(''); // No profile option + var definedNetworks = $.cookie('xcat_' + zhcpToCheck + 'networks').split(','); + for (var i in definedNetworks) { + if( !definedNetworks[i] || 0 === definedNetworks[i].length) continue; + if (!jQuery.trim(definedNetworks[i])) + continue; + + var directoryEntry, interfaceName; + + // Generate directory entry statement for vSwitch, hipersocket, and guest LAN + if (definedNetworks[i].indexOf('VSWITCH ') != -1) { + interfaceName = jQuery.trim(definedNetworks[i].replace('VSWITCH ', '')); + directoryEntry = "TYPE QDIO LAN " + interfaceName; + } else if (definedNetworks[i].indexOf('LAN:HIPERS ') != -1) { + interfaceName = jQuery.trim(definedNetworks[i].replace('LAN:HIPERS ', '')); + directoryEntry = "TYPE HIPERSOCKETS LAN " + interfaceName; + } else { + interfaceName = jQuery.trim(definedNetworks[i].replace('LAN:QDIO ', '')); + directoryEntry = "TYPE QDIO LAN " + interfaceName; + } + + thisNetwork.append(''); + } + + // Update user entry on change + thisNetwork.change(function() { + updateUserEntry(thisTabId); + }); + + thisUserProfile.change(function() { + updateUserEntry(thisTabId); + }); + } + } + }); + } + }); + hcpDiv.append(hcpNodeLabel); + hcpDiv.append(hcpNodeInput); + hcpDiv.append(hcpHiddenInput); + vmAttr.append(hcpDiv); + + // Create an advanced link to set IP address and hostname + var advancedLnk = $(''); + vmAttr.append(advancedLnk); + var advanced = $('
                  ').hide(); + vmAttr.append(advanced); + + var ip = $('
                  '); + advanced.append(ip); + var hostname = $('
                  '); + advanced.append(hostname); + + // Show IP address and hostname inputs on-click + advancedLnk.click(function() { + advanced.toggle(); + }); + + // Create operating system image input + var os = $('
                  '); + var osLabel = $(''); + var osSelect = $(''); + osSelect.append($('')); + + var imageNames = $.cookie('xcat_imagenames').split(','); + if (imageNames) { + imageNames.sort(); + for (var i in imageNames) { + if( !imageNames[i] || 0 === imageNames[i].length) continue; + osSelect.append($('')); + } + } + os.append(osLabel); + os.append(osSelect); + osAttr.append(os); + + // Create user entry input + var defaultChkbox = $('').click(function() { + // Remove any warning messages + $(this).parents('.form').find('.ui-state-error').remove(); + + // Get tab Id + var thisTabId = $(this).parents('.ui-tabs-panel').parents('.ui-tabs-panel').attr('id'); + + // Get objects for HCP, user ID, and OS + var userId = $('#' + thisTabId + ' input[name=userId]'); + var os = $('#' + thisTabId + ' select[name=os]'); + + // Get default user entry when clicked + if ($(this).attr('checked')) { + if (!os.val() || !userId.val()) { + // Show warning message + var warn = createWarnBar('Please specify the operating system and user ID before checking this box'); + warn.prependTo($(this).parents('.form')); + + // Highlight empty fields + jQuery.each([os, userId], function() { + if (!$(this).val()) { + $(this).css('border', 'solid #FF0000 1px'); + } + }); + } else { + // Un-highlight empty fields + jQuery.each([os, userId], function() { + $(this).css('border', 'solid #BDBDBD 1px'); + }); + + // Get profile name + var tmp = os.val().split('-'); + var profile = tmp[3]; + + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'getdefaultuserentry;' + profile, + msg : thisTabId + }, + + success :function(data) { + data = decodeRsp(data); + // Populate user entry + var tabId = data.msg; + var entry = new String(data.rsp); + var userId = $('#' + tabId + ' input[name=userId]').val(); + entry = entry.replace(new RegExp('LXUSR', 'g'), userId); + $('#' + tabId + ' textarea:visible').val(entry); + } + }); + } + } else { + $('#' + thisTabId + ' textarea:visible').val(''); + + // Un-highlight empty fields + jQuery.each([os, userId], function() { + $(this).css('border', 'solid #BDBDBD 1px'); + }); + } + }); + var userEntry = $('
                  '); + userEntry.append($('').append(defaultChkbox, 'Use default')); + + // Add division on basic tab for specifying: memory, # of CPUs, privilege, user profile, and network. + var basicConfig = $('
                  '); + var userProfile = $('
                  '); + var cpuSelect = $('').change(function() { + updateUserEntry('zvmProvisionTab' + inst); + }); + var cpuCount = $('
                  ').append(cpuSelect); + var memorySlider = $('
                  '); + var memorySize = $(''); + var memory = $('
                  ').append(memorySlider, memorySize); + var acceptableMemorySize = ['512M', '1024M', '2G', '3G', '4G', '5G', '6G', '7G', '8G']; + memorySlider.slider({ + value: 0, + min: 0, + max: 8, + step: 1, + slide: function(event, ui) { + $('#basicConfig' + inst + ' input[name=memory]').val(acceptableMemorySize[ui.value]); + + // Update user entry on change + updateUserEntry('zvmProvisionTab' + inst); + } + }); + + // Initialize storage size + memorySize.val(acceptableMemorySize[0]); + + var privilege = $('
                  ' + + '
                  ' + + ' A - Primary system operator
                  ' + + ' B - System resource operator
                  ' + + ' C - System programmer
                  ' + + ' D - Spooling operator
                  ' + + ' E - System analyst
                  ' + + ' F - IBM service representative
                  ' + + ' G - General user
                  ' + + '
                  ' + + '
                  '); + privilege.find('input').change(function() { + updateUserEntry('zvmProvisionTab' + inst); + }); + + var network = $('
                  '); + + var vswitchvlan = $('

                  ' + + '
                  ' + + '
                  '); + vswitchvlan.find('input').change(function() { + updateUserEntry('zvmProvisionTab' + inst); + }); + vswitchvlan.find('select').change(function() { + updateUserEntry('zvmProvisionTab' + inst); + }); + + vswitchvlan.hide(); + basicConfig.append(userProfile, cpuCount, memory, privilege, network, vswitchvlan); + hwTab.add('basicConfig' + inst, 'Basic', basicConfig, false); + + // Add division on advanced tab for specifying user directory entry + hwTab.add('advancedConfig' + inst, 'Advanced', userEntry, false); + + // Create disk table + var diskDiv = $('
                  '); + var diskLabel = $(''); + var diskTable = $('
                  '); + var diskHeader = $(' Type Address Size Mode Pool Password IPLNone
                  '); + // Adjust header width + diskHeader.find('th').css( { + 'width' : '80px' + }); + diskHeader.find('th').eq(0).css( { + 'width' : '20px' + }); + var diskBody = $(''); + var diskFooter = $(''); + + /** + * Add disks + */ + var addDiskLink = $('Add disk'); + addDiskLink.bind('click', function(event) { + // Get list of disk pools + var thisTabId = $(this).parents('.tab').attr('id'); + var thisHcp = $('#' + thisTabId + ' input[name=hcp]').val(); + var definedPools = null; + if (thisHcp) { + // Get node without domain name + var temp = thisHcp.split('.'); + definedPools = $.cookie('xcat_' + temp[0] + 'diskpools').split(','); + } else { + var warning = createWarnBar('You must fill in a hardware control point before adding a disk.'); + var warnDialog = $('
                  ').append(warning); + + // Open dialog + warnDialog.dialog({ + title:'Warning', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function() { + $(this).dialog("close"); + } + } + }); + return false; + } + + // Create a row + var diskRow = $(''); + + // Add remove button + var removeBtn = $(''); + var col = $('').append(removeBtn); + removeBtn.bind('click', function(event) { + diskRow.remove(); + }); + diskRow.append(col); + + // Create disk type drop down + var diskType = $(''); + var diskTypeSelect = $(''); + diskTypeSelect.append('' + + '' + ); + diskType.append(diskTypeSelect); + diskRow.append(diskType); + + // Create disk address input + var diskAddr = $(''); + diskRow.append(diskAddr); + + // Create disk size input + var diskSize = $(''); + diskRow.append(diskSize); + + // Create disk mode input + var diskMode = $(''); + var diskModeSelect = $(''); + diskModeSelect.append('' + + '' + + '' + + '' + + '' + + '' + + '' + ); + diskMode.append(diskModeSelect); + diskRow.append(diskMode); + + // Create disk pool drop down + var diskPool = $(''); + var diskPoolSelect = $(''); + for (var i in definedPools) { + diskPoolSelect.append(''); + } + diskPool.append(diskPoolSelect); + diskRow.append(diskPool); + + // Create disk password input + var diskPw = $(''); + diskRow.append(diskPw); + + // Create IPL checkbox + //var diskIpl = $(''); + var diskIpl = $(''); + diskRow.append(diskIpl); + diskIpl.find('input').change(function() { + updateUserEntry(thisTabId); + }); + + diskBody.append(diskRow); + + // Generate tooltips + diskBody.find('td input[title],select[title]').tooltip({ + position: "top right", + offset: [-4, 4], + effect: "fade", + opacity: 0.7, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + } + }); + }); + + // Create disk table + diskFooter.append(addDiskLink); + diskTable.append(diskHeader); + diskTable.append(diskBody); + diskTable.append(diskFooter); + + diskDiv.append(diskLabel); + diskDiv.append(diskTable); + hwAttr.append(diskDiv); + + // Create zFCP table + var zfcpDiv = $('
                  '); + var zfcpLabel = $(''); + var zfcpTable = $('
                  '); + var zfcpHeader = $(' Address Size Pool Tag Port Name Unit # LOADDEV'); + // Adjust header width + zfcpHeader.find('th').css({ + 'width' : '80px' + }); + zfcpHeader.find('th').eq(0).css({ + 'width' : '20px' + }); + var zfcpBody = $(''); + var zfcpFooter = $(''); + + /** + * Add zFCP devices + */ + var addZfcpLink = $('Add zFCP'); + addZfcpLink.bind('click', function(event) { + // Get list of disk pools + var thisTabId = $(this).parents('.tab').attr('id'); + var thisHcp = $('#' + thisTabId + ' input[name=hcp]').val(); + var definedPools = null; + if (thisHcp) { + // Get node without domain name + var temp = thisHcp.split('.'); + definedPools = $.cookie('xcat_' + temp[0] + 'zfcppools').split(','); + } else { + var warning = createWarnBar('You must fill in a hardware control point before adding a zFCP.'); + var warnDialog = $('
                  ').append(warning); + + // Open dialog + warnDialog.dialog({ + title:'Warning', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function() { + $(this).dialog("close"); + } + } + }); + + } + + // Create a row + var zfcpRow = $(''); + + // Add remove button + var removeBtn = $(''); + var col = $('').append(removeBtn); + removeBtn.bind('click', function(event) { + zfcpRow.remove(); + }); + zfcpRow.append(col); + + // Create disk address input + var zfcpAddr = $(''); + zfcpRow.append(zfcpAddr); + + // Create disk size input + var zfcpSize = $(''); + zfcpRow.append(zfcpSize); + + // Create zFCP pool drop down + var zfcpPool = $(''); + var zfcpPoolSelect = $(''); + for (var i in definedPools) { + zfcpPoolSelect.append(''); + } + zfcpPool.append(zfcpPoolSelect); + zfcpRow.append(zfcpPool); + + // Create disk tag + var zfcpTag = $(''); + zfcpRow.append(zfcpTag); + + // Create device port name + var zfcpPortName = $(''); + zfcpRow.append(zfcpPortName); + + // Create device unit number + var zfcpUnitNo = $(''); + zfcpRow.append(zfcpUnitNo); + + // Create LOADDEV radio button + var zfcpLoaddev = $(''); + zfcpRow.append(zfcpLoaddev); + + zfcpBody.append(zfcpRow); + + // Generate tooltips + zfcpBody.find('td input[title],select[title]').tooltip({ + position: "top right", + offset: [-4, 4], + effect: "fade", + opacity: 0.7, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + } + }); + }); + + zfcpFooter.append(addZfcpLink); + zfcpTable.append(zfcpHeader); + zfcpTable.append(zfcpBody); + zfcpTable.append(zfcpFooter); + + zfcpDiv.append(zfcpLabel); + zfcpDiv.append(zfcpTable); + hwAttr.append(zfcpDiv); + + // Generate tooltips + provNew.find('div input[title],select[title],textarea[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" + } + }); + + // Disable IPL column if advanced tab is selected + hwTab.object().tabs({ + select: function(event, ui) { + // Get provision tab instance + var thisTabId = $(this).parents('.ui-tabs-panel').attr('id'); + var inst = thisTabId.replace('zvmProvisionTab', ''); + + // Disable and de-select IPL device + if (ui.index == 1) { + $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').attr('disabled','disabled'); + } else { + $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').removeAttr('disabled'); + } + + $('#' + thisTabId + ' table:eq(0):visible tbody tr td:nth-child(8) input').removeAttr('checked'); + } + }); + + /** + * Provision new + */ + var provisionBtn = createButton('Provision'); + provisionBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parent().parent().find('.ui-state-error').remove(); + + var ready = true; + var errMsg = ''; + + // Get tab ID + var thisTabId = $(this).parents('.ui-tabs-panel').attr('id'); + // Get provision tab instance + var inst = thisTabId.replace('zvmProvisionTab', ''); + + // Get the selected hardware configuration tab + // Basic tab index = 0 & advanced tab index = 1 + var hwTabIndex = $("#hwConfig" + inst).tabs('option', 'selected'); + + // Check node name, userId, hardware control point, and group + // Check disks and zFCP devices + var inputs = $('#' + thisTabId + ' input:visible'); + for (var i = 0; i < inputs.length; i++) { + // Do not check some inputs + if (inputs.eq(i).attr('name') == 'memory') { + // There should always be a value for memory + // Do not change the border + continue; + } else if (!inputs.eq(i).val() + && inputs.eq(i).attr('type') != 'password' + && inputs.eq(i).attr('name') != 'zfcpTag' + && inputs.eq(i).attr('name') != 'zfcpPortName' + && inputs.eq(i).attr('name') != 'zfcpUnitNo') { + inputs.eq(i).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + inputs.eq(i).css('border', 'solid #BDBDBD 1px'); + } + } + + var selects = $('#' + thisTabId + ' select:visible'); + for (var i = 0; i < selects.length; i++) { + if (!selects.eq(i).val() && selects.eq(i).attr('name') != 'os' && selects.eq(i).attr('name') != 'userProfile' && selects.eq(i).attr('name') != 'network') { + selects.eq(i).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + selects.eq(i).css('border', 'solid #BDBDBD 1px'); + } + } + + if (hwTabIndex == 1) { + // Check user entry + var thisUserEntry = $('#' + thisTabId + ' textarea:visible'); + thisUserEntry.val(thisUserEntry.val().toUpperCase()); + if (!thisUserEntry.val()) { + thisUserEntry.css('border', 'solid #FF0000 1px'); + ready = false; + } else { + thisUserEntry.css('border', 'solid #BDBDBD 1px'); + } + + // Check if user entry contains user ID + var thisUserId = $('#' + thisTabId + ' input[name=userId]:visible'); + var pos = thisUserEntry.val().indexOf('USER ' + thisUserId.val().toUpperCase()); + if (pos < 0) { + + pos = thisUserEntry.val().indexOf('IDENTITY ' + thisUserId.val().toUpperCase()); + if (pos < 0) { + errMsg = errMsg + 'The directory entry does not contain the correct user/identity ID.
                  '; + ready = false; + } + } + } + var hostnameCheck = $('#' + thisTabId + ' input[name=hostname]').val(); + if (hostnameCheck.length > 70) { + errMsg = errMsg + 'The host name cannot be longer than 70 characters.
                  '; + $('#' + thisTabId + ' input[name=hostname]').css('border', 'solid #FF0000 1px'); + ready = false; + } + + // Show error message for missing inputs + if (!ready) { + errMsg = errMsg + 'Please provide a value for each missing field.
                  '; + } + + // If no operating system is specified, create only user entry + os = $('#' + thisTabId + ' select[name=os]:visible'); + + // Check number of disks + var diskRows = $('#' + thisTabId + ' table tr'); + // If an OS is given, disks are needed + if (os.val() && (diskRows.length < 1)) { + errMsg = errMsg + 'You need to add at some disks.
                  '; + ready = false; + } + + // If this is basic mode, check for a disk with IPL radio button and zFCP with LOADDEV button + // Cannot have both. (In advanced mode they create the directory entries.) + if (hwTabIndex == 0) { + // Find a device to be IPLed? + var ECKD_FBA_diskRows = $('#' + thisTabId + ' table:eq(0):visible tbody tr'); + var iplSet = 0; + for (var i = 0; i < ECKD_FBA_diskRows.length; i++) { + var diskArgs = ECKD_FBA_diskRows.eq(i).find('td'); + if (diskArgs.eq(7).find('input').attr("checked") === true) { + iplSet = 1; + break; + } + } + + // Check if zFCP loaddev checked + var zfcpRows = $('#' + thisTabId + ' table:eq(1):visible tbody tr'); + if (zfcpRows.length > 0) { + for ( var i = 0; i < zfcpRows.length; i++) { + var diskArgs = zfcpRows.eq(i).find('td'); + // This is either true or false + var loaddev = diskArgs.eq(7).find('input').attr('checked'); + if (loaddev && iplSet) { + errMsg = errMsg + 'You cannot have both disk IPL and zFCP LOADDEV, can only IPL one device.
                  '; + ready = false; + } + } + } + } + + // If inputs are valid, ready to provision + if (ready) { + // Generate user directory entry if basic tab is selected + if (hwTabIndex == 0) { + updateUserEntry(thisTabId); + } + + if (!os.val()) { + // If no OS is given, create a virtual server + var msg = ''; + if (diskRows.length > 0) { + msg = 'Do you want to create a virtual server without an operating system?'; + } else { + // If no disks are given, create a virtual server (no disk) + msg = 'Do you want to create a virtual server without an operating system or disks?'; + } + + // Open dialog to confirm + var confirmDialog = $('

                  ' + msg + '

                  '); + confirmDialog.dialog({ + title:'Confirm', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + // Disable provision button + provisionBtn.attr('disabled', 'true'); + + // Show loader + $('#zProvisionStatBar' + inst).show(); + $('#zProvisionLoader' + inst).show(); + + // Disable add disk button + addDiskLink.attr('disabled', 'true'); + + // Disable close button on disk table + $('#' + thisTabId + ' table span').unbind('click'); + + // Disable all inputs + var inputs = $('#' + thisTabId + ' input'); + inputs.attr('disabled', 'disabled'); + + // Disable all selects + var selects = $('#' + thisTabId + ' select'); + selects.attr('disabled', 'disabled'); + + // Add a new line at the end of the user entry + var textarea = $('#' + thisTabId + ' textarea'); + var tmp = jQuery.trim(textarea.val()); + textarea.val(tmp + '\n'); + textarea.attr('readonly', 'readonly'); + textarea.css( { + 'background-color' : '#F2F2F2' + }); + + // Get node name + var node = $('#' + thisTabId + ' input[name=nodeName]').val(); + // Get userId + var userId = $('#' + thisTabId + ' input[name=userId]').val(); + // Get hardware control point + var hcp = $('#' + thisTabId + ' input[name=hcp]').val(); + // Get group + var group = $('#' + thisTabId + ' input[name=group]').val(); + // Get IP address and hostname + var ip = $('#' + thisTabId + ' input[name=ip]').val(); + var hostname = $('#' + thisTabId + ' input[name=hostname]').val(); + + // Generate arguments to sent + var args = node + ';zvm.hcp=' + hcp + + ';zvm.userid=' + userId + + ';nodehm.mgt=zvm' + + ';groups=' + group; + if (ip) + args += ';hosts.ip=' + ip; + + if (hostname) + args += ';hosts.hostnames=' + hostname; + + /** + * (1) Define node + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : args, + msg : 'cmd=nodeadd;out=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); + } else { + /** + * Create a virtual server and install OS + */ + + // Disable provision button + $(this).attr('disabled', 'true'); + + // Show loader + $('#zProvisionStatBar' + inst).show(); + $('#zProvisionLoader' + inst).show(); + + // Disable add disk button + addDiskLink.attr('disabled', 'true'); + + // Disable close button on disk table + $('#' + thisTabId + ' table span').unbind('click'); + + // Disable all inputs + var inputs = $('#' + thisTabId + ' input'); + inputs.attr('disabled', 'disabled'); + inputs.css( { + 'background-color' : '#F2F2F2' + }); + + // Disable all selects + var selects = $('#' + thisTabId + ' select'); + selects.attr('disabled', 'disabled'); + selects.css( { + 'background-color' : '#F2F2F2' + }); + + // Add a new line at the end of the user entry + var textarea = $('#' + thisTabId + ' textarea'); + var tmp = jQuery.trim(textarea.val()); + textarea.val(tmp + '\n'); + textarea.attr('readonly', 'readonly'); + textarea.css( { + 'background-color' : '#F2F2F2' + }); + + // Get node name + var node = $('#' + thisTabId + ' input[name=nodeName]').val(); + // Get userId + var userId = $('#' + thisTabId + ' input[name=userId]').val(); + // Get hardware control point + var hcp = $('#' + thisTabId + ' input[name=hcp]').val(); + // Get group + var group = $('#' + thisTabId + ' input[name=group]').val(); + // Get IP address and hostname + var ip = $('#' + thisTabId + ' input[name=ip]').val(); + var hostname = $('#' + thisTabId + ' input[name=hostname]').val(); + + // Generate arguments to sent + var args = node + ';zvm.hcp=' + hcp + + ';zvm.userid=' + userId + + ';nodehm.mgt=zvm' + + ';groups=' + group; + if (ip) + args += ';hosts.ip=' + ip; + + if (hostname) + args += ';hosts.hostnames=' + hostname; + + /** + * (1) Define node + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : args, + msg : 'cmd=nodeadd;out=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateZProvisionNewStatus(data); + } + }); + } + } else { + // Show warning message + var warn = createWarnBar(errMsg); + warn.prependTo($(this).parent().parent()); + } + }); + provNew.append(provisionBtn); + + return provNew; +} +/** + * Remove zprovision loading gif for zhcp and message + * + * @param division holding the gif and message + */ +function removeProvisionLoadingGif(provisionStatBar) { + + // Only remove the status bar message and gif we added, then hide the status bar + var items = provisionStatBar.find('div').children(); + for (var i = 0; i< items.length; i++) { + var nname = items[i].nodeName; + var myid = items[i].id; + if (nname == "B" && myid == "loadzhcp") { + items[i].remove() + } else if (nname == "IMG" && myid == "loadingpic") { + items[i].remove(); + } + } + provisionStatBar.hide(); +} + +/** + * Set hash entry to 0 and check if all are 0. If so call + * removeProvisionLoadingGif + * + * @param division holding the gif and message, and hash, and + * key + */ +function checkProvisionCallsDone(provisionStatBar, table, finishedKey) { + + table[finishedKey] = 0; + + for (var key in table) { + if (table[key] == 1) { + return; // More to do + } + } + + removeProvisionLoadingGif(provisionStatBar); +} + +/** + * Load zVMs into column (service page) + * + * @param col Table column where OS images will be placed + */ +function loadzVMs(col) { + // Get group names and description and append to group column + if (!$.cookie('xcat_zvms')) { + var infoBar = createInfoBar('No selectable z/VM available'); + col.append(infoBar); + return; + } + + var zNames = $.cookie('xcat_zvms').split(','); + + var radio, zBlock, args, zvm, hcp; + for (var i in zNames) { + if( !zNames[i] || 0 === zNames[i].length) continue; + args = zNames[i].split(':'); + zvm = args[0]; + hcp = args[1]; + + // Create block for each group + zBlock = $('
                  ').css({ + 'border': '1px solid', + 'max-width': '200px', + 'margin': '5px auto', + 'padding': '5px', + 'display': 'block', + 'vertical-align': 'middle', + 'cursor': 'pointer', + 'white-space': 'normal' + }).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'); + zBlock.append(radio, $('' + zvm + ' managed by ' + hcp + '')); + zBlock.children('span').css({ + 'display': 'block', + 'margin': '5px', + 'text-align': 'left' + }); + col.append(zBlock); + } +} + +/** + * Load groups into column + * + * @param col Table column where OS images will be placed + */ +function loadSrvGroups(col) { + // Get group names and description and append to group column + if (!$.cookie('xcat_srv_groups')) { + var infoBar = createInfoBar('No selectable group available'); + col.append(infoBar); + return; + } + + var groupNames = $.cookie('xcat_srv_groups').split(','); + + var groupBlock, radio, args, name, ip, hostname, desc; + for (var i in groupNames) { + if( !groupNames[i] || 0 === groupNames[i].length) continue; + 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': 'block', + 'vertical-align': 'middle', + 'cursor': 'pointer', + 'white-space': 'normal' + }).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 + ': ' + desc + '')); + groupBlock.children('span').css({ + 'display': 'block', + 'margin': '5px', + 'text-align': 'left' + }); + col.append(groupBlock); + } +} + +/** + * Load OS images into column + * + * @param col Table column where OS images will be placed + */ +function loadOSImages(col) { + // Get group names and description and append to group column + if (!$.cookie('xcat_srv_imagenames')) { + var infoBar = createInfoBar('No selectable image available'); + col.append(infoBar); + return; + } + + var imgNames = $.cookie('xcat_srv_imagenames').split(','); + + var imgBlock, radio, args, name, desc; + for (var i in imgNames) { + if( !imgNames[i] || 0 === imgNames[i].length) continue; + 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': 'block', + 'vertical-align': 'middle', + 'cursor': 'pointer', + 'white-space': 'normal' + }).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'); + + $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').attr('checked', ''); + $('#select-table tbody tr:eq(0) td:eq(3) input[name="master"]').parents('td').find('div').attr('class', 'ui-state-default'); + }); + radio = $('').css('display', 'none'); + imgBlock.append(radio, $('' + name + ': ' + desc + '')); + imgBlock.children('span').css({ + 'display': 'block', + 'margin': '5px', + 'text-align': 'left' + }); + col.append(imgBlock); + } +} + +/** + * Load golden images into column + * + * @param col Table column where master copies will be placed + */ +function loadGoldenImages(col) { + // Get group names and description and append to group column + if (!$.cookie('xcat_srv_goldenimages')) { + var infoBar = createInfoBar('No selectable master copies available'); + col.append(infoBar); + return; + } + + var imgNames = $.cookie('xcat_srv_goldenimages').split(','); + + var imgBlock, radio, args, name, desc; + for (var i in imgNames) { + if( !imgNames[i] || 0 === imgNames[i].length) continue; + 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': 'block', + 'vertical-align': 'middle', + 'cursor': 'pointer', + 'white-space': 'normal' + }).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'); + + // Un-select zVM and image + $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').attr('checked', ''); + $('#select-table tbody tr:eq(0) td:eq(2) input[name="image"]').parents('td').find('div').attr('class', 'ui-state-default'); + + $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').attr('checked', ''); + $('#select-table tbody tr:eq(0) td:eq(0) input[name="hcp"]').parents('td').find('div').attr('class', 'ui-state-default'); + }); + radio = $('').css('display', 'none'); + imgBlock.append(radio, $('' + name + ': ' + desc + '')); + imgBlock.children('span').css({ + 'display': 'block', + 'margin': '5px', + 'text-align': 'left' + }); + col.append(imgBlock); + } +} + +/** + * Set a cookie for zVM host names (service page) + * + * @param data Data from HTTP request + */ +function setzVMCookies(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var zvms = new Array(); + var hosts = data.rsp[0].split("\n"); + for ( var i = 0; i < hosts.length; i++) { + if (hosts[i] != null && hosts[i] != "") { + zvms.push(hosts[i]); + if (typeof console == "object"){ + console.log("Setting a zVM cookie:<"+hosts[i]+">"); + } + } + } + + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); + $.cookie('xcat_zvms', zvms, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Set a cookie for master copies (service page) + * + * @param data Data from HTTP request + */ +function setGoldenImagesCookies(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1) { + var copies = new Array(); + var tmp = data.rsp[0].split(","); + for ( var i = 0; i < tmp.length; i++) { + if (tmp[i] != null && tmp[i] != "") { + copies.push(tmp[i]); + } + } + + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); + $.cookie('xcat_srv_goldenimages', copies, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Set a cookie for disk pool names of a given node + * + * @param data Data from HTTP request + */ +function setDiskPoolCookies(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var node = data.msg; + var pools = data.rsp[0].split(node + ": "); + var pools2 = []; + for (var j in pools) { + if (pools[j] != "") { + pools2.push(jQuery.trim(pools[j])); + } + } + + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); + $.cookie('xcat_' + node + 'diskpools', pools2, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Set a cookie for zFCP pool names of a given node + * + * @param data Data from HTTP request + */ +function setZfcpPoolCookies(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var node = data.msg; + var pools = data.rsp[0].split(node + ': '); + var pools2 = []; + for (var j in pools) { + if (pools[j] != "") { + pools2.push(jQuery.trim(pools[j])); + } + } + + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); + $.cookie('xcat_' + node + 'zfcppools', pools2, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Set a cookie for zHCP host names + * + * @param zhcps List of zHCPs known + */ +function setzHcpCookies(zhcps) { + if (zhcps.length) { + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); + $.cookie('xcat_zhcps', zhcps, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Set a cookie for z/VM user profile names of a given node + * + * @param data Data from HTTP request + */ +function setUserProfilesCookies(data) { + if (data.rsp.length && data.rsp[0].indexOf("Failed") == -1 && data.rsp[0].indexOf("Error") == -1 ) { + var node = data.msg; + var profiles = data.rsp[0].split(node + ': '); + var profiles2 = []; + for (var j in profiles) { + if (profiles[j] != "") { + profiles2.push(jQuery.trim(profiles[j])); + } + } + + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (60 * 60 * 1000)); + $.cookie('xcat_' + node + 'userprofiles', profiles2, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Create virtual machine (service page) + * + * @param tabId Tab ID + * @param group Group + * @param hcp Hardware control point + * @param img OS image + */ +function createzVM(tabId, group, hcp, img, owner) { + // Submit request to create VM + // webportal provzlinux [group] [hcp] [image] [owner] + var iframe = createIFrame('lib/srv_cmd.php?cmd=webportal&tgt=&args=provzlinux;' + group + ';' + hcp + ';' + img + ';' + owner + '&msg=&opts=flush'); + iframe.prependTo($('#' + tabId)); +} + +/** + * Query the profiles that exists + * + * @param panelId Panel ID + */ +function queryProfiles(panelId) { + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'osimage', + msg : panelId + }, + + success : function(data) { + data = decodeRsp(data); + var panelId = data.msg; + setOSImageCookies(data); + configProfilePanel(panelId); + } + }); +} + +/** + * Panel to configure directory entries and disks for a profile + * + * @param panelId Panel ID + */ +function configProfilePanel(panelId) { + // Wipe panel clean + $('#' + panelId).empty(); + + // Add info bar + $('#' + panelId).append(createInfoBar('Create, edit, and delete profiles for the self-service portal. It is important to note the default z/VM user ID for any profile should be LXUSR.')); + + // Create table + var tableId = 'zvmProfileTable'; + var table = new DataTable(tableId); + table.init(['', 'Profile', 'Disk pool', 'Disk size', 'Directory entry']); + + // Insert profiles into table + var profiles = $.cookie('xcat_profiles').split(','); + profiles.push('default'); // Add default profile + for (var i in profiles) { + if (profiles[i]) { + // Columns are: profile, selectable, description, disk pool, disk size, and directory entry + var cols = new Array(profiles[i], '', '', ''); + + // Add remove button where id = user name + cols.unshift(''); + + // Add row + table.add(cols); + } + } + + // Append datatable to tab + $('#' + panelId).append(table.object()); + + // Turn into datatable + $('#' + tableId).dataTable({ + 'iDisplayLength': 50, + 'bLengthChange': false, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + + // Create action bar + var actionBar = $('
                  ').css("width", "450px"); + + // Create a profile + var createLnk = $('Create'); + createLnk.click(function() { + profileDialog(); + }); + + // Edit a profile + var editLnk = $('Edit'); + editLnk.click(function() { + var profiles = $('#' + tableId + ' input[type=checkbox]:checked'); + for (var i in profiles) { + var profile = profiles.eq(i).attr('name'); + if (profile) { + // Column order is: profile, selectable, disk pool, disk size, and directory entry + var cols = profiles.eq(i).parents('tr').find('td'); + var pool = cols.eq(2).text(); + var size = cols.eq(3).text(); + var entry = cols.eq(4).html().replace(new RegExp('
                  ', 'g'), '\n'); + + editProfileDialog(profile, pool, size, entry); + } + } + }); + + // Delete a profile + var deleteLnk = $('Delete'); + deleteLnk.click(function() { + var profiles = getNodesChecked(tableId); + if (profiles) { + deleteProfileDialog(profiles); + } + }); + + // Refresh profiles table + var refreshLnk = $('Refresh'); + refreshLnk.click(function() { + queryProfiles(panelId); + }); + + // Create an action menu + var actionsMenu = createMenu([refreshLnk, createLnk, editLnk, deleteLnk]); + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); + $('#' + tableId + '_wrapper').prepend(menuDiv); + menuDiv.append(actionBar); + $('#' + tableId + '_filter').appendTo(menuDiv); + + // Resize accordion + $('#' + tableId).parents('.ui-accordion').accordion('resize'); + + // Query directory entries and disk pool/size for each profile + for (var i in profiles) { + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'getdefaultuserentry;' + profiles[i], + msg : 'out=' + panelId + ';profile=' + profiles[i] + }, + + success : function(data) { + data = decodeRsp(data); + insertDirectoryEntry(data); + } + }); + + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'getzdiskinfo;' + profiles[i], + msg : 'out=' + panelId + ';profile=' + profiles[i] + }, + + success : function(data) { + data = decodeRsp(data); + insertDiskInfo(data); + } + }); + } +} + +/** + * Insert the directory entry into the profile table + * + * @param data Data from HTTP request + */ +function insertDirectoryEntry(data) { + var tableId = 'zvmProfileTable'; + var args = data.msg.split(';'); + + var profile = args[1].replace('profile=', ''); + + // Do not continue if there is nothing + if (!data.rsp.length) + return; + + var entry = data.rsp[0].replace(new RegExp('\n', 'g'), '
                  '); + + // Get the row containing the profile + var rowPos = findRow(profile, '#' + tableId, 1); + if (rowPos < 0) + return; + + // Update the directory entry column + var dTable = $('#' + tableId).dataTable(); + dTable.fnUpdate(entry, rowPos, 4, false); + + // Adjust table styling + $('#' + tableId + ' td:nth-child(5)').css({ + 'text-align': 'left' + }); + adjustColumnSize(tableId); +} + +/** + * Insert the disk info into the profile table + * + * @param data Data from HTTP request + */ +function insertDiskInfo(data) { + var tableId = 'zvmProfileTable'; + var args = data.msg.split(';'); + + var profile = args[1].replace('profile=', ''); + + // Do not continue if there is nothing + if (!data.rsp.length) + return; + + // Get the row containing the profile + var rowPos = findRow(profile, '#' + tableId, 1); + if (rowPos < 0) + return; + + // Update the disk info columns + var dTable = $('#' + tableId).dataTable(); + + var tmp = ""; + var pool = ""; + var eckdSize = 0; + var info = data.rsp[0].split('\n'); + for (var i in info) { + if (info[i].indexOf('diskpool') > -1) { + tmp = info[i].split('='); + pool = jQuery.trim(tmp[1]); + + dTable.fnUpdate(pool, rowPos, 2, false); + } if (info[i].indexOf('eckd_size') > -1) { + tmp = info[i].split('='); + eckdSize = jQuery.trim(tmp[1]); + + dTable.fnUpdate(eckdSize, rowPos, 3, false); + } + } + + // Adjust table styling + adjustColumnSize(tableId); +} + +/** + * Open profile dialog + */ +function profileDialog() { + // Create form to add profile + var dialogId = 'zvmCreateProfile'; + var profileForm = $('
                  '); + + // Create info bar + var info = createInfoBar('Configure the default settings for a profile'); + profileForm.append(info); + + // Insert profiles into select + var profileSelect = $(''); + var profiles = $.cookie('xcat_profiles').split(','); + profiles.push('default'); // Add default profile + for (var i in profiles) { + if (profiles[i]) { + profileSelect.append($('')); + } + } + + profileForm.append($('
                  ').append(profileSelect)); + profileForm.append('
                  '); + profileForm.append('
                  '); + profileForm.append('
                  ').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/cmd.php', - dataType : 'json', - data : { - cmd : 'chdef', - tgt : '', - args : '-t;node;-o;' + node + ';usercomment=' + comments, - msg : 'out=nodesTab;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; -} - -/** - * Create a tool tip for node status - * - * @return Tool tip - */ -function createStatusToolTip() { - // Create tooltip container - var toolTip = $('
                  ').css({ - 'width': '150px', - 'font-weight': 'normal' - }); - - // Create info text - var info = $('

                  ').css({ - 'white-space': 'normal' - }); - info.append('Click here to refresh the node status. To configure the xCAT monitor, '); - - // Create link to turn on xCAT monitoring - var monitorLnk = $('click here').css({ - 'color': '#58ACFA', - 'font-size': '10px' - }); - - // Open dialog to configure xCAT monitor - monitorLnk.bind('click', function(){ - // Check if xCAT monitor is enabled - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'monls', - tgt : '', - args : 'xcatmon', - msg : '' - }, - - success : openConfXcatMon - }); - }); - - info.append(monitorLnk); - toolTip.append(info); - - return toolTip; -} - -/** - * Create a tool tip for power status - * - * @return Tool tip - */ -function createPowerToolTip() { - // Create tooltip container - var toolTip = $('
                  Click here to refresh the power status
                  ').css({ - 'width': '150px', - 'white-space': 'normal', - 'font-weight': 'normal' - }); - return toolTip; -} - -/** - * Create a tool tip for monitoring status - * - * @return Tool tip - */ -function createMonitorToolTip() { - // Create tooltip container - var toolTip = $('
                  Click here to refresh the monitoring status
                  ').css({ - 'width': '150px', - 'white-space': 'normal', - 'font-weight': 'normal' - }); - return toolTip; -} - -/** - * Open dialog to configure xCAT monitor - * - * @param data Data returned from HTTP request - */ -function openConfXcatMon(data) { - // Create info bar - var info = createInfoBar('Configure the xCAT monitor. Select to enable or disable the monitor below.'); - var dialog = $('
                  '); - dialog.append(info); - - // Create status area - var statusArea = $('
                  ').css('padding-top', '10px'); - var label = $(''); - statusArea.append(label); - - // Get xCAT monitor status - var status = data.rsp[0]; - var buttons; - // If xCAT monitor is disabled - if (status.indexOf('not-monitored') > -1) { - status = $('Disabled').css('padding', '0px 5px'); - statusArea.append(status); - - // Create enable and cancel buttons - buttons = { - "Enable": function(){ - // Enable xCAT monitor - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'monstart', - tgt : '', - args : 'xcatmon', - msg : '' - }, - - success : function(data){ - openDialog('info', data.rsp[0]); - } - }); - $(this).dialog("close"); - }, - "Cancel": function(){ - $(this).dialog("close"); - } - }; - } else { - status = $('Enabled').css('padding', '0px 5px'); - statusArea.append(status); - - // Create disable and cancel buttons - buttons = { - "Disable": function(){ - // Disable xCAT monitor - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'monstop', - tgt : '', - args : 'xcatmon', - msg : '' - }, - - success : function(data){ - openDialog('info', data.rsp[0]); - } - }); - $(this).dialog("close"); - }, - "Cancel": function(){ - $(this).dialog("close"); - } - }; - } - - dialog.append(statusArea); - - // Open dialog - dialog.dialog({ - modal: true, - width: 500, - buttons: buttons - }); -} - -/** - * Show chdef output - * - * @param data Data returned from HTTP request - */ -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); -} - -/** - * Set node attributes - * - * @param data Data returned from HTTP request - */ -function setNodeAttrs(data) { - // Clear hash table containing definable node attributes - nodeAttrs = new Array(); - - // Get definable attributes - var attrs = data.rsp[2].split(/\n/); - - // Go through each line - var attr, key, descr; - for (var i in attrs) { - attr = attrs[i]; - - // If the line is not empty - if (attr) { - // If the line has the attribute name - if (attr.indexOf(':') && attr.indexOf(' ')) { - // Get attribute name and description - key = jQuery.trim(attr.substring(0, attr.indexOf(':'))); - descr = jQuery.trim(attr.substring(attr.indexOf(':') + 1)); - - // Remove arrow brackets - descr = descr.replace(new RegExp('<|>', 'g'), ''); - - // Set hash table where key = attribute name and value = description - nodeAttrs[key] = descr; - } else { - // Remove arrow brackets - attr = attr.replace(new RegExp('<|>', 'g'), ''); - - // Append description to hash table - nodeAttrs[key] = nodeAttrs[key] + '\n' + attr; - } - } // End of if - } // End of for -} - - -/** - * Load the discover z/VM virtual systems page - * - * @param tgtNode Target node to set properties - */ -function discoverVMNodes(tgtNodes) { - var fs, legend, htmlLine; - - // Get nodes tab - var tab = getNodesTab(); - - // Generate new tab ID - var inst = 0; - var newTabId = 'discoverVMNodesTab' + inst; - while ($('#' + newTabId).length) { - // If one already exists, generate another one - inst = inst + 1; - newTabId = 'discoverVMNodesTab' + inst; - } - - // Open new tab - // Create set properties form - var discoverVMNodesForm = $('
                  '); - - // Create info bar - var infoBar = createInfoBar( 'Initiate, stop or query the status of z/VM node discovery. ' + - 'To initiate discovery, specify discovery parameters and click on the Discover button. ' + - 'To stop an on-going discovery related to a z/VM host, specify the host node name and '+ - 'click on the Stop button. ' + - 'To obtain the status of discovery for a particular host, specify the host node name and '+ - 'click on the Stop button.' - ); - discoverVMNodesForm.append(infoBar); - - // Create the status bar and hide it. - var statBarId = 'statusBar_' + newTabId; - //var statBar = $( '
                  ' ); - //discoverVMNodesForm.append( statBar ); - statBar = createStatusBar( statBarId ); - statBar.hide(); - discoverVMNodesForm.append( statBar ); - - // Create Host fieldset - fs = $('
                  '); - legend = $('z/VM Host'); - fs.append(legend); - discoverVMNodesForm.append(fs); - - // Target node or group - htmlLine = $('
                  '); - discoverVMNodesForm.append( htmlLine ); - - // Create Discovery Parameters fieldset - fs = $('
                  '); - legend = $('Discovery Parameters'); - fs.append( legend ); - discoverVMNodesForm.append( fs ); - - // Create an input for each definable attribute - var div, label, input, descr, value; - - // Define DefineTo radio buttons - div = $('
                  ').css( 'display', 'inline-block' ).css( 'vertical-align', 'top' ); - div.append( '' ); - div.append( '
                • xCAT and OpenStack
                • ' ); - div.append( '
                • xCAT only
                • ' ); - div.append( '
                • OpenStack only (only already discovered xCAT nodes)
                • ' ); - discoverVMNodesForm.append( div ); - discoverVMNodesForm.append( '
                  ' ); - - // Userid filter - divUserid = newTabId + "_divUserid"; - div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); - div.append( '' ); - div.append( '' ).css( 'margin-top', '5px' ); - discoverVMNodesForm.append( div ); - discoverVMNodesForm.append( '
                  ' ); - - // IP address filter - divIP = newTabId + "_divIP"; - div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); - div.append( '' ); - div.append( '' ).css( 'margin-top', '5px' ); - discoverVMNodesForm.append( div ); - discoverVMNodesForm.append( '
                  ' ); - - // Group name input - divGroup = newTabId + '_divGroup'; - div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); - div.append( '' ); - div.append( '' ).css( 'margin-top', '5px' ); - discoverVMNodesForm.append( div ); - discoverVMNodesForm.append( '
                  ' ); - - // Node Name Format input - divNodename = newTabId + '_divNodename'; - div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); - div.append( '' ); - div.append( '' ).css( 'margin-top', '5px' ); - discoverVMNodesForm.append( div ); - discoverVMNodesForm.append( '
                  ' ); - discoverVMNodesForm.find('#' + divNodename).hide(); - - // OpenStack operand input - divOpenStackOps = newTabId + '_divOpenStackOps'; - div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); - div.append( '' ); - div.append( '' ).css( 'margin-top', '5px' ); - div.append( '
                  ' ); - div.append( '' ); - div.append( '' ).css( 'margin-top', '5px' ); - discoverVMNodesForm.append( div ); - discoverVMNodesForm.append( '
                  ' ); - - // Define Verbose radio buttons - div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ).css( 'text-align', 'top' ); - div.append( '' ); - div.append( '
                • Normal response, showing only important information
                • ' ); - div.append( '
                • Verbose response, normal response plus additional information (e.g. reason a system is ignored)
                • ' ); - discoverVMNodesForm.append( div ); - discoverVMNodesForm.append( '
                  ' ); - - // Generate tooltips - discoverVMNodesForm.find('div input[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - } - }); - - // Show appropriate input fields for defineto choices. - discoverVMNodesForm.change(function(){ - var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val(); - if ( defineTo == 'both' ) { - discoverVMNodesForm.find('#' + divUserid).show(); - discoverVMNodesForm.find('#' + divIP).show(); - discoverVMNodesForm.find('#' + divGroup).show(); - discoverVMNodesForm.find('#' + divOpenStackOps).show(); - discoverVMNodesForm.find('#' + divNodename).hide(); - } else if ( defineTo == 'xcatonly' ) { - discoverVMNodesForm.find('#' + divUserid).show(); - discoverVMNodesForm.find('#' + divIP).show(); - discoverVMNodesForm.find('#' + divGroup).show(); - discoverVMNodesForm.find('#' + divOpenStackOps).hide(); - discoverVMNodesForm.find('#' + divNodename).show(); - } else if ( defineTo == 'openstackonly' ) { - discoverVMNodesForm.find('#' + divUserid).hide(); - discoverVMNodesForm.find('#' + divIP).hide(); - discoverVMNodesForm.find('#' + divGroup).hide(); - discoverVMNodesForm.find('#' + divOpenStackOps).show(); - discoverVMNodesForm.find('#' + divNodename).hide(); - } - }); - - - // Discover nodes button action - var discoverBtn = createButton('Discover'); - discoverBtn.click(function() { - var argList = ''; - var filter = ''; - - var hosts = $(this).parent().find('input[name=hosts]').val(); - if ( hosts != '' ) { - argList = 'zvmhost=' + hosts; - } - - var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val(); - argList = argList + '||defineto=' + defineTo; - - var verbose = $(this).parent().find('input[name="verbose"]:checked').val(); - if ( verbose == 'yes' ) { - argList = argList + '||--verbose'; - } - - var useridFilter = $(this).parent().find('input[name=useridFilter]').val(); - if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( useridFilter != '' )) { - argList = argList + '||useridfilter=' + useridFilter; - } - - var ipFilter = $(this).parent().find('input[name=ipFilter]').val(); - if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( ipFilter != '' )) { - argList = argList + '||ipfilter=' + ipFilter; - } - - var group = $(this).parent().find('input[name=group]').val(); - if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( group != '' )) { - argList = argList + '||groups=' + group; - } - - var nodeNameFmt = $(this).parent().find('input[name=nodeNameFmt]').val(); - if ( defineTo == 'xcatonly' && nodeNameFmt != '' ) { - argList = argList + '||nodenameformat=' + nodeNameFmt; - } - - var openStackProj = $(this).parent().find('input[name=openStackProj]').val(); - var openStackUser = $(this).parent().find('input[name=openStackUser]').val(); - if ((( defineTo == 'both' ) || ( defineTo == 'openstackonly' )) && - (( openStackProj != '' ) || ( openStackUser != '' ))) { - if ( openStackProj != '' ) { - osArgs = '--project ' + openStackProj; - } else { - osArgs = ''; - } - if ( openStackUser != '' ) { - if ( osArgs != '' ) { - osArgs = osArgs + ' --user ' + openStackUser; - } else { - osArgs = '--user ' + openStackUser; - } - } - argList = argList + "||openstackoperands='" + osArgs + "'"; - } - - var out = $('

                  '); - out.append( 'Starting node discovery...' ); - out.append( '
                  ' ); - out.append( 'If node discovery is a short running task then its response will follow. If, however, the time it takes to complete discovery exceeds the http request timeout of a few minutes then the discovery response will not be returned to the browser. The status and list buttons can be used to obtained status on the discovery and see what systems have been discovered.' ); - $( '#' + statBarId ).find( 'div' ).append( out ); - statBar.show(); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodediscoverstart', - tgt : '', - args : argList, - att : '', - msg : statBarId - }, - success: function(data) { - updateDiscoverStatusBar( data, 1 ); - } - }); - - }); - discoverVMNodesForm.append(discoverBtn); - - // Status button - var statusBtn = createButton('Status'); - statusBtn.click( function() { - var hosts = $(this).parent().find('input[name=hosts]').val(); - var out = $('

                  '); - out.append( 'Querying status for discovery on ' + hosts + '...' ); - out.append( '
                  ' ); - $( '#' + statBarId ).find( 'div' ).append( out ); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodediscoverstatus', - tgt : '', - args : '--zvmhost||' + hosts, - att : '', - msg : statBarId - }, - success: function(data) { - updateDiscoverStatusBar( data, 1 ); - } - }); - - }); - discoverVMNodesForm.append( statusBtn ); - - // List button - var listBtn = createButton('List'); - listBtn.click( function() { - var hosts = $(this).parent().find('input[name=hosts]').val(); - var out = $('

                  '); - out.append( 'Listing systems discovered by the latest discovery on ' + hosts + '...' ); - out.append( '
                  ' ); - $( '#' + statBarId ).find( 'div' ).append( out ); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodediscoverls', - tgt : '', - args : '-t||zvm||--zvmhost||' + hosts, - att : '', - msg : statBarId - }, - success: function(data) { - updateDiscoverStatusBar( data, 1 ); - } - }); - }); - discoverVMNodesForm.append( listBtn ); - - // Stop button - var stopBtn = createButton('Stop'); - stopBtn.click(function() { - var hosts = $(this).parent().find('input[name=hosts]').val(); - var out = $('

                  '); - out.append( 'Stopping discovery on ' + hosts + '...' ); - out.append( '
                  ' ); - $( '#' + statBarId ).find( 'div' ).append( out ); - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodediscoverstop', - tgt : '', - args : '--zvmhost||' + hosts, - att : '', - msg : statBarId - }, - success: function(data) { - updateDiscoverStatusBar( data, 1 ); - } - }); - }); - discoverVMNodesForm.append( stopBtn ); - - // Append to discover tab - tab.add(newTabId, 'Discover', discoverVMNodesForm, true); - - // Select new tab - tab.select(newTabId); -} - - -/** - * Update discovery status bar - * - * @param data Data returned from HTTP request - */ -function updateDiscoverStatusBar( data, preformatted ) { - var statBarId = data.msg; - var rsp = data.rsp; - var statBar = $( '#' + statBarId ); - - // Go through response to make it readable in the status bar. - var out = $('

                  '); - for ( var i in rsp ) { - if ( preformatted == 1 ) { - out.append( '
                  ' + rsp[i] + '
                  ' ); - } else { - out.append( rsp[i] + '
                  ' ); - } - } - - // Write response to status bar and show the bar. - $( '#' + statBarId ).find( 'div' ).append( out ); - statBar.show(); -} - -/** - * Load set node properties page - * - * @param tgtNode Target node to set properties - */ -function editNodeProps(tgtNode) { - // Get nodes tab - var tab = getNodesTab(); - - // Generate new tab ID - var inst = 0; - var newTabId = 'editPropsTab' + inst; - while ($('#' + newTabId).length) { - // If one already exists, generate another one - inst = inst + 1; - newTabId = 'editPropsTab' + inst; - } - - // Open new tab - // Create set properties form - var editPropsForm = $('
                  '); - - // Create info bar - var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.'); - editPropsForm.append(infoBar); - - // Create an input for each definable attribute - var div, label, input, descr, value; - // Set node attribute - origAttrs[tgtNode]['node'] = tgtNode; - for (var key in nodeAttrs) { - // If an attribute value exists - if (origAttrs[tgtNode][key]) { - // Set the value - value = origAttrs[tgtNode][key]; - } else { - value = ''; - } - - // Create label and input for attribute - div = $('
                  ').css('display', 'inline-table'); - label = $('').css('vertical-align', 'middle'); - input = $('').css('margin-top', '5px'); - - // Change border to blue onchange - input.bind('change', function(event) { - $(this).css('border-color', 'blue'); - }); - - div.append(label); - div.append(input); - editPropsForm.append(div); - } - - // Change style for last division - div.css({ - 'display': 'block', - 'margin': '0px 0px 10px 0px' - }); - - // Generate tooltips - editPropsForm.find('div input[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - } - }); - - // Save changes - var saveBtn = createButton('Save'); - saveBtn.click(function() { - // Get all inputs - var inputs = $('#' + newTabId + ' input'); - - // Go through each input - var args = ''; - var attrName, attrVal; - inputs.each(function(){ - // If the border color is blue - if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') { - // Change border color back to normal - $(this).css('border-color', ''); - - // Get attribute name and value - attrName = $(this).parent().find('label').text().replace(':', ''); - attrVal = $(this).val(); - - // Build argument string - if (args) { - // Handle subsequent arguments - args += ';' + attrName + '=' + attrVal; - } else { - // Handle the 1st argument - args += attrName + '=' + attrVal; - } - } - }); - - // Send command to change node attributes - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chdef', - tgt : '', - args : '-t;node;-o;' + tgtNode + ';' + args, - msg : 'out=' + newTabId + ';tgt=' + tgtNode - }, - - success: showChdefOutput - }); - }); - editPropsForm.append(saveBtn); - - // Cancel changes - var cancelBtn = createButton('Cancel'); - cancelBtn.click(function() { - // Close the tab - tab.remove($(this).parent().parent().attr('id')); - }); - editPropsForm.append(cancelBtn); - - // Append to discover tab - tab.add(newTabId, 'Edit', editPropsForm, true); - - // Select new tab - tab.select(newTabId); -} - -/** - * Open set node attributes dialog - */ -function openSetAttrsDialog() { - // Open new tab - // Create set properties form - var setPropsForm = $('
                  '); - - // Create info bar - var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.'); - setPropsForm.append(infoBar); - - // Create an input for each definable attribute - var div, label, input, descr, value; - for (var key in nodeAttrs) { - value = ''; - - // Create label and input for attribute - div = $('
                  ').css('display', 'inline'); - label = $('').css('vertical-align', 'middle'); - input = $('').css('margin-top', '5px'); - - // Change border to blue onchange - input.bind('change', function(event) { - $(this).css('border-color', 'blue'); - }); - - div.append(label); - div.append(input); - setPropsForm.append(div); - } - - // Change style for last division - div.css({ - 'display': 'block', - 'margin': '0px 0px 10px 0px' - }); - - // Generate tooltips - setPropsForm.find('div input[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Enable vertical scroll - setPropsForm.css('overflow', 'auto'); - - // Open form as a dialog - setPropsForm.dialog({ - title: 'Set attributes', - modal: true, - close: function(){ - $(this).remove(); - }, - height: 400, - width: 800, - buttons: { - "Save": function() { - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get all inputs - var inputs = $(this).find('input'); - - // Go through each input - var args = ''; - var tgtNode, attrName, attrVal; - inputs.each(function(){ - // If the border color is blue - if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') { - // Change border color back to normal - $(this).css('border-color', ''); - - // Get attribute name and value - attrName = $(this).parent().find('label').text().replace(':', ''); - attrVal = $(this).val(); - - // Get node name - if (attrName == 'node') { - tgtNode = attrVal; - } else { - // Build argument string - if (args) { - // Handle subsequent arguments - args += ';' + attrName + '=' + attrVal; - } else { - // Handle the 1st argument - args += attrName + '=' + attrVal; - } - } - } - }); - - // Send command to change node attributes - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chdef', - tgt : '', - args : '-t;node;-o;' + tgtNode + ';' + args, - msg : 'node=' + tgtNode - }, - - /** - * Show results - * - * @param data - * Data returned from HTTP request - * @return Nothing - */ - success: function(data) { - // Get output - var out = data.rsp; - var node = data.msg.replace('node=', ''); - - // Go through output and append to paragraph - var msg = ''; - for (var i in out) { - if (!msg) { - msg = node + ': ' + out[i]; - } else { - msg += '
                  ' + node + ': ' + out[i]; - } - } - - openDialog('info', msg); - } - }); - - // Close dialog - $(this).dialog( "close" ); - }, - "Cancel": function(){ - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Turn on monitoring for a given node - * - * @param node Node to monitor on or off - * @param monitor Monitor state, on or off - */ -function monitorNode(node, monitor) { - // Show ganglia loader - var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); - gangliaCol.find('img').show(); - - if (monitor == 'on') { - // Append loader to warning bar - var warningBar = $('#nodesTab').find('.ui-state-error p'); - if (warningBar.length) { - warningBar.append(createLoader('')); - } - - if (node) { - // Check if ganglia RPMs are installed - $.ajax( { - url : 'lib/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 - */ - 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/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'gangliastart;' + data.msg + ';-r', - msg : data.msg - }, - - success : function(data) { - // Remove any warnings - $('#nodesTab').find('.ui-state-error').remove(); - - // Update datatable - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'gangliastatus;' + data.msg, - msg : '' - }, - - success : loadGangliaStatus - }); - } - }); - } // End of if (warn) - } // End of function(data) - }); - } else { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'gangliastart', - msg : '' - }, - - success : function(data) { - // Remove any warnings - $('#nodesTab').find('.ui-state-error').remove(); - } - }); - } // End of if (node) - } else { - var args; - if (node) { - args = 'gangliastop;' + node + ';-r'; - } else { - args = 'gangliastop'; - } - - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : args, - msg : '' - }, - - success : function(data) { - // Hide ganglia loader - var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); - gangliaCol.find('img').hide(); - } - }); - } -} - -/** - * Install Ganglia on a given node - * - * @param node Node to install Ganglia on - */ -function installGanglia(node) { - var iframe = createIFrame('lib/cmd.php?cmd=webrun&tgt=&args=installganglia;' + node + '&msg=' + node + '&opts=flush'); - iframe.prependTo($('#nodesTab')); - - // Turn on Ganglia for node - monitorNode(node, 'on'); -} - -/** - * After nodes are loaded, load more information based on different hardware architectures - * - * @param group Group name - */ -function advancedLoad(group){ - var tempIndex = 0; - var tableHeaders = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); - var colNameHash = new Object(); - var colName = ''; - var archCol = 0, hcpCol = 0; - - // Find out the column name and their index - for (tempIndex = 0; tempIndex < tableHeaders.size(); tempIndex++){ - var header = tableHeaders.eq(tempIndex); - // Skip headers that are links, e.g. status, power, and monitor - if (header.find('a').size() > 0){ - continue; - } - - colName = header.text(); - - if (colName) { - colNameHash[colName] = tempIndex; - } - } - - // If there is no arch column, exit because you cannot distinguish hardware type - if (!colNameHash['arch']) { - return; - } - - if (!colNameHash['hcp']) { - return; - } - archCol = colNameHash['arch']; - hcpCol = colNameHash['hcp']; - - // Get hardware control point - var rows = $('#' + nodesTableId + ' tbody tr'); - var hcps = new Object(); - var rowsNum = rows.size(); - for (var j = 0; j < rowsNum; j++) { - var val = rows.eq(j).find('td').eq(hcpCol).html(); - var archval = rows.eq(j).find('td').eq(archCol).html(); - if (-1 == archval.indexOf('390')){ - continue; - } - hcps[val] = 1; - } - - if (Object.keys(hcps).length == 0) { - openDialog('warn', "No node found with hcp column filled in and 390 arch!"); - return; - } - // Get Nodes info bar - //var nodeInfoBar = getNodesTabInfoBar(); - //nodeInfoBar.append("\nEntering Advanced Load...\n") - - var args; - var shortzHcps = new Array(); - var zhcpHash = new Object(); - for (var h in hcps) { - // Get node without domain name - args = h.split('.'); - - if (!zhcpHash[args[0]]) { - - shortzHcps.push(args[0]); - zhcpHash[args[0]] = 1; - - // If there are no disk pools or network names cookie for this hcp - if (!$.cookie('xcat_' + args[0] + 'diskpools') || !$.cookie('xcat_' + args[0] + 'networks')) { - // Check if SMAPI is online - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsvm', - tgt : args[0], - args : '', - msg : 'group=' + group + ';hcp=' + args[0] - }, - - // Load hardware control point specific info - // Get disk pools and network names - success : loadHcpInfo - }); - } - } - } // End of for - - // Save zHCPs as a cookie - setzHcpCookies(shortzHcps); - - // Retrieve z/VM hypervisors and their zHCPs - if (!$.cookie('xcat_zvms')) { - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webportal', - tgt : '', - args : 'lszvm', - msg : '' - }, - - success : function(data) { - setzVMCookies(data); - } - }); - } -} - -/** - * Jump to provision page on-click - * - * @param tgtNodes Target nodes - */ -function jump2Provision(tgtNodes){ - var nodeArray = tgtNodes.split(','); - var nodeName = ''; - var index = 0; - var archType = ''; - var errorMsg = ''; - var master = ''; - var tftpserver = ''; - var nfsserver = ''; - var diaDiv = $('
                  '); - - // Check the first node's arch type - for (index in nodeArray){ - nodeName = nodeArray[index]; - - // Skip if node does not have arch - if (!origAttrs[nodeName]['arch']){ - errorMsg = 'Nodes should have arch defined! '; - break; - } - - if (index == 0) { - archType = origAttrs[nodeName]['arch']; - } - - // Skip if nodes do not have same arch - if (archType != origAttrs[nodeName]['arch']){ - errorMsg = 'Nodes should belong to the same arch!
                  '; - break; - } - } - - // Skip if nodes do not have MAC address - for (index in nodeArray){ - if (!origAttrs[nodeName]['mac'] || !origAttrs[nodeName]['ip']){ - errorMsg += 'Nodes should have the IP and MAC addresses defined!
                  '; - break; - } - } - - if (archType.indexOf('390') != -1) { - errorMsg += 'Please use the provision page'; - } - - // Open dialog to show error message - if (errorMsg){ - diaDiv.append(createWarnBar(errorMsg)); - diaDiv.dialog({ - modal: true, - close: function(){ - $(this).remove(); - }, - width: 400, - buttons: { - 'Close': function(){ - $(this).dialog('destroy'); - } - } - }); - - return; - } - - if (origAttrs[nodeName]['xcatmaster']) { - master = origAttrs[nodeName]['xcatmaster']; - } - - if (origAttrs[nodeName]['tftpserver']) { - tftpserver = origAttrs[nodeName]['tftpserver']; - } - - if (origAttrs[nodeName]['nfsserver']) { - nfsserver = origAttrs[nodeName]['nfsserver']; - } - - window.location.href = 'provision.php?nodes=' + tgtNodes + '&arch=' + archType + '&master=' + master + - '&tftpserver=' + tftpserver + '&nfsserver=' + nfsserver; -} \ No newline at end of file +/** + * Global variables + *Test Git update in MCP_DEV branch */ +var nodesTab; // Nodes tabs +var origAttrs = new Object(); // Original node attributes +var nodeAttrs; // Node attributes +var nodesList; // Node list +var nodesTableId = 'nodesDatatable'; // Nodes datatable ID +var nodesTabInfoBar; +var builtInXCAT = 1; // 1 means xCAT shipped with zVM + +/** + * Set node tab + * + * @param tab + * Tab object + * @return Nothing + */ +function setNodesTab(tab) { + nodesTab = tab; +} + +/** + * Get node tab + * + * @return Tab object + */ +function getNodesTab() { + return nodesTab; +} + +/** + * Set node tab info bar. Used by zvmUtils.js + * + * @param tab + * infobar object + * @return Nothing + */ +function setNodesTabInfoBar(tabinfo) { + nodesTabInfoBar = tabinfo; +} + +/** + * Get node tab info bar + * + * @return Tab info bar object + */ +function getNodesTabInfoBar() { + return nodesTabInfoBar; +} + +/** + * Get node list + * + * @return Node list + */ +function getNodesList() { + return nodesList; +} + +/** + * Get nodes table ID + * + * @return Nodes table ID + */ +function getNodesTableId() { + return nodesTableId; +} + +/** + * Load nodes page + */ +function loadNodesPage() { + // If groups are not already loaded + if (!$('#groups').length) { + // Create a groups division + var groups = $('
                  '); + var nodes = $('
                  '); + $('#content').append(groups); + $('#content').append(nodes); + + // Create loader and info bar + groups.append(createLoader()); + + // Get groups + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'extnoderange', + tgt : '/.*', + args : 'subgroups', + msg : '' + }, + + // Load groups + success : function(data){ + data = decodeRsp(data); + loadGroups(data); + + var cookieGroup = $.cookie('xcat_selectgrouponnodes'); + if (cookieGroup) { + $('#groups .groupdiv div').each(function(){ + if ($(this).text() == cookieGroup){ + $(this).trigger('click'); + return false; + } + }); + } else { + // Trigger the first group click event + $('#groups .groupdiv div').eq(0).trigger('click'); + } + } + }); + } +} + +/** + * Show cluster summary in pie charts + * + * @param groupName Group name + */ +function loadPieSummary(groupName){ + var summaryTable = '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
                  '; + $('#summaryTab').append(summaryTable); + $('#summaryTab .summarypie').append(createLoader()); + + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'summary;' + groupName, + msg : '' + }, + + success:function(data) { + data = decodeRsp(data); + for (var i in data.rsp) { + drawPieSummary(i, data.rsp[i]); + } + } + }); +} + +/** + * Get nodes information and draw pie chart + * + * @param index Node index + * @param valuePair Node information key value pairing + */ +function drawPieSummary(index, valuePair){ + var position = 0; + var key = ''; + var val = ''; + var chartTitle = ''; + var dataArray = []; + var tempArray = []; + var container = $('#summaryTab .summarypie').eq(index); + + position = valuePair.indexOf('='); + chartTitle = valuePair.substr(0, position); + tempArray = valuePair.substr(position + 1).split(';'); + + for (var i in tempArray) { + position = tempArray[i].indexOf(':'); + key = tempArray[i].substr(0, position); + val = Number(tempArray[i].substr(position + 1)); + dataArray.push([key,val]); + } + + container.empty(); + + var plot = $.jqplot(container.attr('id'), [dataArray], { + title: chartTitle, + seriesDefaults: { + renderer: $.jqplot.PieRenderer, + rendererOptions: { + padding: 5, + fill: true, + shadow: true, + shadowOffset: 2, + shadowDepth: 5, + shadowAlpha: 0.07, + dataLabels : 'value', + showDataLabels: true + } + }, + legend: { + show:true, + location: 'e' + } + }); +} + +/** + * Load groups + * + * @param data Data returned from HTTP request + */ +function loadGroups(data) { + // Remove loader + $('#groups').find('img').remove(); + + // Save group in cookie + var groups = data.rsp; + setGroupsCookies(data); + + // Create a list of groups + $('#groups').append('
                  Groups
                  '); + var grouplist= $('
                  '); + // Create a link for each group + for (var i = 0; i < groups.length; i++) { + grouplist.append('
                  ' + groups[i] + '
                  '); + } + + $('#groups').append(grouplist); + + // Bind the click event + $('#groups .groupdiv div').bind('click', function(){ + var thisGroup = $(this).text(); + $('#groups .groupdiv div').removeClass('selectgroup'); + $(this).addClass('selectgroup'); + + // Save selected group into cookie + $.cookie('xcat_selectgrouponnodes', thisGroup, { expires: 7, path: '/xcat', secure:true }); + + drawNodesArea(thisGroup,'',thisGroup); + }); + + // Make a link to add nodes + $('#groups').append('
                  '); + $('#groups #adddiv').append(mkAddNodeLink()); +} + +/** + * Empty the nodes area and add three tabs for nodes result + * + * @param targetgroup The name range for nodels command + * @param cmdargs Filter arguments for nodels command + * @param message The useful information from the HTTP request + */ +function drawNodesArea(targetgroup, cmdargs, message){ + // Clear nodes division + $('#nodes').empty(); + + // Create a tab for this group + var tab = new Tab('nodesPageTabs'); + setNodesTab(tab); + tab.init(); + $('#nodes').append(tab.object()); + tab.add('summaryTab', 'Summary', '', false); + tab.add('nodesTab', 'Nodes', '', false); + if (builtInXCAT == 0) { + tab.add('graphTab', 'Graphic', '', false); + } + + // Load nodes table when tab is selected + $('#nodesPageTabs').bind('tabsselect', function(event, ui) { + // Load summary when tab is selected + if (!$('#summaryTab').children().length && ui.index == 0) { + loadPieSummary(targetgroup); + } + + // Load nodes table when tab is selected + else if (!$('#nodesTab').children().length && ui.index == 1) { + // Create loader + $('#nodesTab').append($('
                  ').append(createLoader())); + + // To improve performance, get all nodes within selected group + // Get node definitions only for first 50 nodes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodels', + tgt : targetgroup, + args : cmdargs, + msg : message + }, + + /** + * Get node definitions for first 50 nodes + * + * @param data Data returned from HTTP request + */ + success : function(data) { + data = decodeRsp(data); + var rsp = data.rsp; + var group = data.msg; + + // Save nodes in a list so it can be accessed later + nodesList = new Array(); + for (var i in rsp) { + if (rsp[i][0]) { + nodesList.push(rsp[i][0]); + } + } + + // Sort nodes list + nodesList.sort(); + + // Get first 50 nodes + var nodes = ''; + for (var i = 0; i < nodesList.length; i++) { + if (i > 49) { + break; + } + + nodes += nodesList[i] + ','; + } + + // Remove last comma + nodes = nodes.substring(0, nodes.length-1); + + // Get nodes definitions + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : nodes, + msg : targetgroup + }, + + success : function(data) { + data = decodeRsp(data); + loadNodes(data); + } + }); + + } + }); + } + + // Load graphical layout when tab is selected + else if ((builtInXCAT == 0) && (!$('#graphTab').children().length && ui.index == 2)) { + // For the graphical tab, check the graphical data first + createPhysicalLayout(nodesList); + } + + }); + + // Get last view (if any) + // This can be summary, nodes, or graphic + if ($.cookie('xcat_tabindex_history')) { + var order = $.cookie('xcat_tabindex_history').split(','); + order[0] = parseInt(order[0]); + order[1] = parseInt(order[1]); + if (order[0] == 0 || order[1] == 0) { + // For some reason, you cannot trigger a select of index 0 + loadPieSummary(targetgroup); + } else if (order[0] == 1 || order[0] == 2) { + $('#nodesPageTabs').tabs('select', order[0]); + } else if (order[1] == 1 || order[1] == 2) { + $('#nodesPageTabs').tabs('select', order[1]); + } else { + loadPieSummary(targetgroup); + } + } else { + loadPieSummary(targetgroup); + } +} + +/** + * Make a link to add nodes + * + * @returns Link to add nodes + */ +function mkAddNodeLink() { + // Create link to add nodes + var addNodeLink = $('+ Add node'); + addNodeLink.click(function() { + // Create info bar + var info = createInfoBar('Select the hardware management for the new node range'); + + // Create form to add node + var addNodeForm = $('
                  '); + addNodeForm.append(info); + if (builtInXCAT == 0) { + addNodeForm.append('
                  ' + + '' + + '
                  '); + } else { + addNodeForm.append('
                  ' + + '' + + '
                  '); + } + + // Create advanced link to set advanced node properties + var advanced = $('
                  '); + var advancedLnk = $('Advanced').css({ + 'cursor': 'pointer', + 'color': '#0000FF' + }); + advancedLnk.click(function() { + // Get node attributes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : '-t;node;-h', + msg : '' + }, + + /** + * Set node attributes and open dialog + * + * @param data Data returned from HTTP request + */ + success : function(data) { + data = decodeRsp(data); + // Save node attributes + setNodeAttrs(data); + // Open a dialog to set node attributes + openSetAttrsDialog(); + } + }); + + // Close dialog + addNodeForm.dialog('destroy').remove(); + }); + advanced.append(advancedLnk); + addNodeForm.append(advanced); + + // Open dialog to add node + addNodeForm.dialog({ + modal: true, + width: 400, + title:'Add node', + close: function() {$(this).remove();}, + buttons: { + 'Ok': function() { + // Get hardware management + var mgt = $(this).find('select[name=mgt]').val(); + + var plugin; + switch(mgt) { + case "kvm": + plugin = new kvmPlugin(); + break; + case "esx": + plugin = new esxPlugin(); + break; + case "blade": + plugin = new bladePlugin(); + break; + case "hmc": + plugin = new hmcPlugin(); + break; + case "ipmi": + plugin = new ipmiPlugin(); + break; + case "zvm": + plugin = new zvmPlugin(); + break; + } + + $(this).dialog('destroy').remove(); + plugin.addNode(); + }, + 'Cancel': function(){ + $(this).dialog('destroy').remove(); + } + } + }); + + }); + + // Generate tooltips + addNodeLink.tooltip({ + position: 'center right', + offset: [-2, 10], + effect: 'fade', + opacity: 0.7, + predelay: 800 + }); + + return addNodeLink; +} + +/** + * Load nodes belonging to a given group + * + * @param data Data returned from HTTP request + */ +function loadNodes(data) { + // Clear the tab before inserting the table + $('#nodesTab').children().remove(); + + // Data returned + var rsp = data.rsp; + // Group name + var group = data.msg; + // Hash of Node attributes + var attrs = new Object(); + // Node attributes + var headers = new Object(); + + // Variable to send command and request node status + var getNodeStatus = true; + + // Clear hash table containing node attributes + origAttrs = ''; + + var node, args; + for (var i in rsp) { + // Get node name + if (rsp[i].indexOf('Object name:') > -1) { + var temp = 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 = rsp[i].split('=', 2); + var key = jQuery.trim(args[0]); + var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1)); + + // Create a hash table + attrs[node][key] = val; + headers[key] = 1; + + // If node status is available + if (key == 'status') { + // Do not request node status + getNodeStatus = false; + } + } + + // Add nodes that are not in data returned + for (var i in nodesList) { + if (!attrs[nodesList[i]]) { + // Create attributes list and save node name + attrs[nodesList[i]] = new Object(); + attrs[nodesList[i]]['node'] = nodesList[i]; + } + } + + // Save attributes in hash table + origAttrs = attrs; + + // Sort headers + var sorted = new Array(); + for (var key in headers) { + // Do not put comments and status in twice + if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) { + 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 nodesTable = new DataTable(nodesTableId); + nodesTable.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('status') < 0) { + var val = attrs[node][key]; + if (val) { + row.push(val); + } else { + row.push(''); + } + } + } + + // Add the row to the table + nodesTable.add(row); + } + + // Clear the tab before inserting the table + $('#nodesTab').children().remove(); + + // Create info bar for nodes tab + var info = createInfoBar('Double-click on a cell to edit a node\'s properties. Click outside the table to save changes. Hit the Escape key to ignore changes.'); + $('#nodesTab').append(info); + info.id = 'NodesInfoBar'; + setNodesTabInfoBar(info); + + // Create action bar + var actionBar = $('
                  ').css("width", "400px"); + + /** + * Create menu for actions to perform against a given node + */ + + // Power on + var powerOnLnk = $('Power on'); + powerOnLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + powerNode(tgtNodes, 'on'); + } + }); + + // Power off + var powerOffLnk = $('Power off'); + powerOffLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + + var msg = 'Do you want to power off: ' + tgtNodes + '?'; + // Open dialog to confirm + var confirmDialog = $('

                  ' + msg + '

                  '); + confirmDialog.dialog({ + title:'Confirm', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + powerNode(tgtNodes, 'off'); + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); + } + }); + + // Power softoff + var powerSoftoffLnk = $('Shutdown'); + powerSoftoffLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + var msg = 'Do you want to shutdown: ' + tgtNodes + '?'; + // Open dialog to confirm + var confirmDialog = $('

                  ' + msg + '

                  '); + confirmDialog.dialog({ + title:'Confirm', + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + "Ok": function(){ + powerNode(tgtNodes, 'softoff'); + $(this).dialog("close"); + }, + "Cancel": function() { + $(this).dialog("close"); + } + } + }); + } + }); + if (builtInXCAT == 0) { + // Turn monitoring on + var monitorOnLnk = $('Monitor on'); + monitorOnLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + monitorNode(tgtNodes, 'on'); + } + }); + + // Turn monitoring off + var monitorOffLnk = $('Monitor off'); + monitorOffLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + monitorNode(tgtNodes, 'off'); + } + }); + } + + // Clone + var cloneLnk = $('Clone'); + cloneLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId).split(','); + for (var i in tgtNodes) { + var mgt = getNodeAttr(tgtNodes[i], 'mgt'); + + // Create an instance of the plugin + var plugin; + switch(mgt) { + case "kvm": + plugin = new kvmPlugin(); + break; + case "esx": + plugin = new esxPlugin(); + break; + case "zvm": + plugin = new zvmPlugin(); + break; + } + if (mgt == "zvm") { + var nodeOS = getNodeAttr(tgtNodes[i], 'os'); + var nodeArch = getNodeAttr(tgtNodes[i], 'arch'); + plugin.loadClonePage(tgtNodes[i], nodeOS, nodeArch); + } else { + plugin.loadClonePage(tgtNodes[i]); + } + + } + }); + + // Delete + var deleteLnk = $('Delete'); + deleteLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + loadDeletePage(tgtNodes); + } + }); + + // Unlock Function + var unlockLnk = $('Unlock'); + unlockLnk.click(function() { + + // Get the "master" value from the site table. + var siteMaster; + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'site', + msg : 'cmd=tabdump site;' + }, + + success : function(data) { + data = decodeRsp(data); + var outId = $(data.msg); + var props = data.rsp; + if ( jQuery.isArray(data.rsp) ) { + for (var i in data.rsp) { + if ( data.rsp[i].indexOf('"master"') == 0 ) { + siteMaster = data.rsp[i].slice( 10, -3 ); + } + } + } else { + if ( data.rsp.indexOf('"master"') == 0 ) { + siteMaster = data.rsp.slice( 10, -3 ); + } + } + + // Process the nodes that were checked. + var tgtNodes = getNodesChecked(nodesTableId).split(','); + var normalNodes = ''; + var mnNode = ''; + for (var i in tgtNodes) { + var nodeIP = getNodeAttr( tgtNodes[i], 'ip' ); + if ( nodeIP == siteMaster ) { + if ( mnNode == '' ) { + // Only one xCAT node will have the same address as + // the site master IP address and this is the + // xCAT MN. + mnNode = tgtNodes[i]; + } + } else { + if ( normalNodes == '' ) { + normalNodes = tgtNodes[i]; + } else { + normalNodes = normalNodes + "," + tgtNodes[i]; + } + } + } + + if ( normalNodes != '' ) { + loadUnlockPage( normalNodes ); + } + if ( mnNode != '' ) { + loadUnlockNonNodesPage( mnNode ); + } + } + }); + }); + + // Run script + var scriptLnk = $('Run script'); + scriptLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + loadScriptPage(tgtNodes); + } else { + openDialog('warn', "No nodes checked!"); + } + }); + + // Migrate VM + var migrateLnk = $('Migrate'); + migrateLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId).split(','); + var mgt = "", tmp = ""; + var fromhcp = ""; + for (var i in tgtNodes) { + tmp = getNodeAttr(tgtNodes[i], 'mgt'); + fromhcp += getNodeAttr(tgtNodes[i], 'hcp') + ','; + if (!mgt) { + mgt = tmp + } else { + if (tmp != mgt) { + openDialog('warn', "You can pick only one type (mgt) of node to migrate!"); + return; + } + } + } + + // Create an instance of the plugin + var plugin; + switch(mgt) { + // Only hypervisors support migration + case "kvm": + plugin = new kvmPlugin(); + break; + case "esx": + plugin = new esxPlugin(); + break; + case "zvm": + plugin = new zvmPlugin(); + break; + } + if (mgt == "zvm") { + plugin.loadMigratePage(tgtNodes, fromhcp); + } else { + plugin.loadMigratePage(tgtNodes); + } + }); + + // Update + var updateLnk = $('Update'); + updateLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + loadUpdatenodePage(tgtNodes); + } + }); + + // Set boot state + var setBootStateLnk = $('Set boot state'); + setBootStateLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + loadNodesetPage(tgtNodes); + } + }); + + // Boot to network + var boot2NetworkLnk = $('Boot to network'); + boot2NetworkLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + loadNetbootPage(tgtNodes); + } + }); + + // Provision node + var provisionLnk = $('Provision'); + provisionLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes){ + // Jump directly to the provision page + jump2Provision(tgtNodes); + } + }); + + // Remote console + var rcons = $('Open console'); + rcons.bind('click', function(event){ + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + loadRconsPage(tgtNodes); + } + }); + + // Discovery + var discoverLnk = $('Discover systems'); + discoverLnk.bind( 'click', function(event) { + var tgtNodes = getNodesChecked(nodesTableId).split(','); + if ( tgtNodes ) { + var hosts; + for (var i in tgtNodes) { + var hostType = getNodeAttr( tgtNodes[i], 'hosttype' ); + if ( hostType == 'zvm' ) { + if ( hosts ) { + hosts += "," + tgtNodes[i]; + } else { + hosts = tgtNodes[i]; + } + + } else { + openDialog('warn', tgtNodes[i] + " does not have a hosttype of 'zvm': " + hostType ); + } + } + if ( hosts ) { + discoverVMNodes( hosts ); + } + } else { + openDialog('warn', "No nodes checked!"); + } + }); + + // Edit properties + var editProps = $('Edit properties'); + editProps.bind('click', function(event){ + var tgtNodes = getNodesChecked(nodesTableId).split(','); + for (var i in tgtNodes) { + editNodeProps(tgtNodes[i]); + } + }); + + // Install Ganglia + var installMonLnk = $('Install monitoring'); + installMonLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + installGanglia(tgtNodes); + } + }); + + // Scan + var rscanLnk = $('Scan'); + rscanLnk.bind('click', function(event){ + var tgtNodes = getNodesChecked(nodesTableId); + if (tgtNodes) { + loadRscanPage(tgtNodes); + } + }); + + // Event log + var logLnk = $('Event log'); + logLnk.click(function() { + var tgtNodes = getNodesChecked(nodesTableId).split(','); + for (var i in tgtNodes) { + var mgt = getNodeAttr(tgtNodes[i], 'mgt'); + + // Create an instance of the plugin + var plugin; + switch(mgt) { + case "kvm": + plugin = new kvmPlugin(); + break; + case "esx": + plugin = new esxPlugin(); + break; + case "blade": + plugin = new bladePlugin(); + break; + case "hmc": + plugin = new hmcPlugin(); + break; + case "ipmi": + plugin = new ipmiPlugin(); + break; + case "zvm": + plugin = new zvmPlugin(); + break; + } + + plugin.loadLogPage(tgtNodes[i]); + } + }); + + // Actions + var actionsLnk = 'Actions'; + if (builtInXCAT == 0) { + if (group == 'hosts') { + var actsMenu = createMenu([deleteLnk]); + } else { + var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, monitorOnLnk, monitorOffLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]); + } + } else { + if (group == 'hosts') { + var actsMenu = createMenu([deleteLnk]); + } else { + var actsMenu = createMenu([cloneLnk, deleteLnk, migrateLnk, powerOnLnk, powerOffLnk, scriptLnk, powerSoftoffLnk]); + } + } + + // Configurations + var configLnk = 'Configuration'; + if (builtInXCAT == 0) { + if (group == 'hosts') { + var configMenu = createMenu([editProps]); + } else { + var configMenu = createMenu([editProps, logLnk, installMonLnk, rscanLnk, unlockLnk, updateLnk]); + } + } else { + if (group == 'hosts') { + var configMenu = createMenu([ discoverLnk, editProps ]); + } else { + var configMenu = createMenu([editProps, logLnk, rscanLnk, unlockLnk, updateLnk]); + } + } + + // Provision + var provLnk = 'Provision'; + if (builtInXCAT == 0) { + var provMenu = createMenu([boot2NetworkLnk, rcons, setBootStateLnk, provisionLnk]); + } else { + var provMenu = createMenu([boot2NetworkLnk, setBootStateLnk]); + } + + /** + * Refresh button + */ + var refreshBtn = createButton('Refresh'); + refreshBtn.click(function() { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + var zhcpsCheck = $.cookie('xcat_zhcps').split(','); + var zhcpHash = new Object(); + for (var h in zhcpsCheck) { + if (!zhcpHash[zhcpsCheck[h]]) { + + zhcpHash[zhcpsCheck[h]] = 1; + if (typeof console == "object"){ + console.log("zhcp check for <"+zhcpsCheck[h]+">"); + } + + // Check if SMAPI is online + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : zhcpsCheck[h], + args : '', + msg : 'group=refreshgroups' + ';hcp=' + zhcpsCheck[h] + }, + + // Load hardware control point specific info + // Get disk pools and network names + success : function(data) { + data = decodeRsp(data); + loadHcpInfo(data); + } + }); + } + } + + window.location.reload(); + }); + refreshBtn.css({'width': '80px'}); + refreshBtn.css({'height': '27px'}); + //refreshBtn.css('vertical-align', 'top'); + refreshBtn.css({'align': 'top'}); + + // Create an action menu + var actionsMenu; + if (group == 'hosts') { + actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ] ]); + } else { + actionsMenu = createMenu([ [ actionsLnk, actsMenu ], [ configLnk, configMenu ], [ provLnk, provMenu ] ]); + } + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + actionBar.append(refreshBtn); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Insert action bar and nodes datatable + $('#nodesTab').append(nodesTable.object()); + + // Turn table into a datatable + var nodesDatatable = $('#' + nodesTableId).dataTable({ + 'iDisplayLength': 50, + 'bLengthChange': false, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + + // Filter table when enter key is pressed + $('#' + nodesTableId + '_filter input').unbind(); + $('#' + nodesTableId + '_filter input').bind('keyup', function(e){ + if (e.keyCode == 13) { + var table = $('#' + nodesTableId).dataTable(); + table.fnFilter($(this).val()); + + // If there are nodes found, get the node attributes + if (!$('#' + nodesTableId + ' .dataTables_empty').length) { + getNodeAttrs(group); + } + } + }); + + // Load node definitions when next or previous buttons are clicked + $('#' + nodesTableId + '_next, #' + nodesTableId + '_previous').click(function() { + getNodeAttrs(group); + }); + + /** + * Change how datatable behaves + */ + + // Do not sort ping, power, and comment column + var cols = $('#' + nodesTableId + ' thead tr th').click(function() { + getNodeAttrs(group); + }); + var checkboxCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(0)'); + var pingCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)'); + var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)'); + var monitorCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); + var commentCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(5)'); + checkboxCol.unbind('click'); + pingCol.unbind('click'); + powerCol.unbind('click'); + monitorCol.unbind('click'); + commentCol.unbind('click'); + + // Create enough space for loader to be displayed + // Center align power, ping, and comments + $('#' + nodesTableId + ' td:nth-child(3),td:nth-child(4),td:nth-child(5)').css({'text-align': 'center'}); + + // No minimum width for comments column + $('#' + nodesTableId + ' tbody tr td:nth-child(6)').css('text-align', 'center'); + + // Instead refresh the node, power, and monitor status + pingCol.find('span a').click(function() { + refreshNodeStatus(group, nodesTableId); + }); + powerCol.find('span a').click(function() { + refreshPowerStatus(group, nodesTableId); + }); + monitorCol.find('span a').click(function() { + refreshGangliaStatus(group, nodesTableId); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); // #
                  '); + update.append(createInfoBar('Updating table ')); + + update.dialog({ + title: 'Updating', + modal: true, + width: 300, + position: 'center' + }); + } +} + +/** + * Add nodes to datatable + * + * @param data Data returned from HTTP request + */ +function addNodes2Table(data) { + // Data returned + var rsp = data.rsp; + // Group name + var group = data.msg; + // Hash of node attributes + var attrs = new Object(); + // Node attributes + var headers = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr th'); + + // Variable to send command and request node status + var getNodeStatus = true; + + // Go through each attribute + var node, args; + for (var i in rsp) { + // Get node name + if (rsp[i].indexOf('Object name:') > -1) { + var temp = rsp[i].split(': '); + node = jQuery.trim(temp[1]); + + // Create a hash for node attributes + attrs[node] = new Object(); + i++; + } + + // Get key and value + args = rsp[i].split('=', 2); + var key = jQuery.trim(args[0]); + var val = jQuery.trim(rsp[i].substring(rsp[i].indexOf('=') + 1, rsp[i].length)); + + // Create a hash table + attrs[node][key] = val; + // Save attributes in original hash table + origAttrs[node][key] = val; + + // If node status is available + if (key == 'status') { + // Do not request node status + getNodeStatus = false; + } + } + + // Set the first five headers + var headersCol = new Object(); + headersCol['node'] = 1; + headersCol['status'] = 2; + headersCol['power'] = 3; + headersCol['monitor'] = 4; + headersCol['comments'] = 5; + + // Go through each header + for (var i = 6; i < headers.length; i++) { + // Get the column index + headersCol[headers.eq(i).html()] = i; + } + + // Go through each node + var datatable = $('#' + nodesTableId).dataTable(); + var rows = datatable.fnGetData(); + for (var node in attrs) { + // Get row containing node + var nodeRowPos = 0; + for (var i in rows) { + // If column contains node + if (rows[i][1].indexOf('>' + node + '<') > -1) { + nodeRowPos = i; + break; + } + } + + // Get node status + var status = ''; + if (attrs[node]['status']){ + status = attrs[node]['status'].replace('sshd', 'ping'); + } + + rows[nodeRowPos][headersCol['status']] = status; + + // Go through each header + for (var key in headersCol) { + // Do not put comments and status in twice + if (key != 'usercomment' && key != 'status' && key.indexOf('status') < 0) { + var val = attrs[node][key]; + if (val) { + rows[nodeRowPos][headersCol[key]] = val; + } + } + } + + // Update row + datatable.fnUpdate(rows[nodeRowPos], parseInt(nodeRowPos), undefined, false); + + // Insert node comments + // This is done after datatable is updated because + // you cannot insert an object using fnUpdate() + 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 icon for node comments + var tipID = node + 'Tip'; + var commentsCol = $('#' + node).parent().parent().find('td').eq(5); + + // Create tooltip + var icon = $('').css({ + 'width': '18px', + 'height': '18px' + }); + + var tip = createCommentsToolTip(comments); + var span = $('').append(icon); + span.append(tip); + commentsCol.append(span); + + // Generate tooltips + icon.tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + relative: true, + delay: 500 + }); + } + + // Enable node link + $('.node').bind('click', loadNode); + + // Close dialog for updating table + $('.ui-dialog-content').dialog('destroy').remove(); + + /** + * Enable editable columns + */ + // Do not make 1st, 2nd, 3rd, 4th, 5th, or 6th column editable + $('#' + nodesTableId + ' td:not(td:nth-child(1),td:nth-child(2),td:nth-child(3),td:nth-child(4),td:nth-child(5),td:nth-child(6))').editable( + function(value, settings) { + // If users did not do changes, return the value directly + // jeditable save the old value in this.revert + if ($(this).attr('revert') == value){ + return value; + } + // Get column index + var colPos = this.cellIndex; + + // Get row index + var dTable = $('#' + nodesTableId).dataTable(); + var rowPos = dTable.fnGetPosition(this.parentNode); + + // Update datatable + dTable.fnUpdate(value, rowPos, colPos, false); + + // Get table headers + var headers = $('#' + nodesTableId + ' thead tr th'); + + // Get node name + var node = $(this).parent().find('td a.node').text(); + // Get attribute name + var attrName = jQuery.trim(headers.eq(colPos).text()); + // Get column value + var value = $(this).text(); + + // Build argument + var args = attrName + '=' + value; + + // Send command to change node attributes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chdef', + tgt : '', + args : '-t;node;-o;' + node + ';' + args, + msg : 'out=nodesTab;tgt=' + node + }, + + success: function(data) { + data = decodeRsp(data); + showChdefOutput(data); + } + }); + + return value; + }, { + onblur : 'submit', // Clicking outside editable area submits changes + type : 'textarea', + placeholder: ' ', + event : 'dblclick', + height : '30px' // The height of the text area + }); + + // If request to get node status is made + if (getNodeStatus) { + // Get node status + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodestat', + tgt : group, + args : '-u', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadNodeStatus(data); + } + }); + } else { + // Hide status loader + var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)'); + statCol.find('img').hide(); + } + + /** + * Additional ajax requests need to be made for zVM + */ + advancedLoad(group); + adjustColumnSize(nodesTableId); +} + +/** + * Load the status of Ganglia for a given group + * + * @param data Data returned from HTTP request + */ +function loadGangliaStatus(data) { + // Get datatable + var datatable = $('#' + nodesTableId).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]); + + if (node) { + // Get the row containing the node + rowNum = findRow(node, '#' + nodesTableId, 1); + + // Update the power status column + datatable.fnUpdate(status, rowNum, 4); + } + } + + // Hide Ganglia loader + var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); + gangliaCol.find('img').hide(); + adjustColumnSize(nodesTableId); +} + +/** + * Refresh the status of Ganglia for each node + * + * @param group Group name + */ +function refreshGangliaStatus(group) { + // Show ganglia loader + var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); + gangliaCol.find('img').show(); + + // Get power status for nodes shown + var nodes = getNodesShown(nodesTableId); + + // Get the status of Ganglia + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'gangliastatus;' + nodes, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadGangliaStatus(data); + } + }); +} + +/** + * Load power status for each node + * + * @param data Data returned from HTTP request + */ +function loadPowerStatus(data) { + var dTable = $('#' + nodesTableId).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, '#' + nodesTableId, 1); + + // Update the power status column + dTable.fnUpdate(status, rowPos, 3); + } + + // Hide power loader + var powerCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)'); + powerCol.find('img').hide(); + adjustColumnSize(nodesTableId); +} + +/** + * Refresh power status for each node + * + * @param group Group name + * @param tableId Table to update node status + */ +function refreshPowerStatus(group, tableId) { + // Show power loader + var powerCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)'); + powerCol.find('img').show(); + + // Get power status for nodes shown + var nodes = getNodesShown(tableId); + + // Get power status + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rpower', + tgt : nodes, + args : 'stat', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadPowerStatus(data); + } + }); +} + +/** + * Load node status for each node + * + * @param data Data returned from HTTP request + */ +function loadNodeStatus(data) { + var dTable = $('#' + nodesTableId).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, '#' + nodesTableId, 1); + + // Update ping status column + dTable.fnUpdate(status, rowPos, 2, false); + } + + // Hide status loader + var statCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)'); + statCol.find('img').hide(); + adjustColumnSize(nodesTableId); +} + +/** + * Refresh ping status for each node + * + * @param group Group name + * @param tableId Table to update node status + */ +function refreshNodeStatus(group, tableId) { + // Show ping loader + var pingCol = $('#' + tableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(2)'); + pingCol.find('img').show(); + + // Get power status for nodes shown + var nodes = getNodesShown(tableId); + + // Get the node status + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodestat', + tgt : nodes, + args : '-u', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadNodeStatus(data); + } + }); +} + +/** + * Load inventory for given node + * + * @param e Windows event + */ +function loadNode(e) { + if (!e) { + e = window.event; + } + + // Get node that was clicked + var node = (e.target) ? e.target.id : e.srcElement.id; + var mgt = getNodeAttr(node, 'mgt'); + + // Create an instance of the plugin + var plugin; + switch(mgt) { + case "kvm": + plugin = new kvmPlugin(); + break; + case "esx": + plugin = new esxPlugin(); + break; + case "blade": + plugin = new bladePlugin(); + break; + case "hmc": + plugin = new hmcPlugin(); + break; + case "ipmi": + plugin = new ipmiPlugin(); + break; + case "zvm": + plugin = new zvmPlugin(); + break; + } + + // Get tab area where a new tab will be inserted + var myTab = getNodesTab(); + var inst = 0; + var newTabId = 'nodeTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'nodeTab' + inst; + } + // Reset node process + $.cookie('xcat_' + node + 'Processes', 0, { path: '/xcat', secure:true }); + + // Add new tab, only if one does not exist + var loader = createLoader(newTabId + 'TabLoader'); + loader = $('
                  ').append(loader); + myTab.add(newTabId, node, loader, true); + + // Get node inventory + var msg = 'out=' + newTabId + ',node=' + node; + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rinv', + tgt : node, + args : 'all', + msg : msg + }, + + success : function(data) { + data = decodeRsp(data); + plugin.loadInventory(data); + } + }); + + // Select new tab + myTab.select(newTabId); +} + +/** + * Unlock a node by setting the ssh keys + * + * @param tgtNodes Nodes to unlock + */ +function loadUnlockPage(tgtNodes) { + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var instance = 0; + var newTabId = 'unlockTab' + instance; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + instance = instance + 1; + newTabId = 'unlockTab' + instance; + } + + // Create status bar, hide on load + var statBarId = 'unlockStatusBar' + instance; + var statBar = createStatusBar(statBarId).hide(); + + // Create loader + var loader = createLoader(''); + statBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('Give the root password for this node range to setup its SSH keys.'); + + // Create unlock form + var unlockForm = $('
                  '); + unlockForm.append(statBar, infoBar); + + // Create VM fieldset + var vmFS = $('
                  '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + unlockForm.append(vmFS); + + var vmAttr = $('
                  '); + vmFS.append($('
                  ')); + vmFS.append(vmAttr); + + vmAttr.append('
                  '); + vmAttr.append('
                  '); + + // 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" + } + }); + + /** + * Ok + */ + var unlockBtn = createButton('Unlock'); + unlockBtn.css({ + 'width': '80px', + 'display': 'block' + }); + unlockBtn.click(function() { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + // If a password is given + var password = $('#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px'); + if (password.val()) { + // Setup SSH keys + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'unlock;' + tgtNodes + ';' + password.val(), + msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes + }, + + success : function(data) { + data = decodeRsp(data); + updateStatusBar(data); + } + }); + + // Show status bar + statBar.show(); + + // Disable all inputs and Ok button + $('#' + newTabId + ' input').attr('disabled', 'disabled'); + $(this).attr('disabled', 'true'); + } else { + // Show warning message + var warn = createWarnBar('You are missing some values!'); + warn.prependTo($(this).parents('.ui-tabs-panel')); + password.css('border', 'solid #FF0000 1px'); + } + }); + + unlockForm.append(unlockBtn); + tab.add(newTabId, 'Unlock', unlockForm, true); + tab.select(newTabId); +} + +function loadUnlockNonNodesPage( tgtNodes ) { + + // Get nodes tab + var tab = getNodesTab(); + var fs, legend; + + // Generate new tab ID + var instance = 0; + var newTabId = 'unlockNonNodesTab' + instance; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + instance = instance + 1; + newTabId = 'unlockNonNodesTab' + instance; + } + + // Create info bar and status bar + var infoBar = createInfoBar( 'Unlock systems that have not been defined to xCAT. Either:
                  ' + + '-Create a script to install the xCAT Management Node\'s public key on the target systems, or
                  ' + + '-Unlock system(s) directly using their IP address(es) ' + + '(Specify multiple systems by separating the addresses with a comma),
                  ' + + '-Show the xCAT Management Node\'s public key to use to unlock the system.' ); + + var statBarId = 'unlockNonNodesStatusBar' + instance; + var statBar = createStatusBar(statBarId).hide(); + var loader = createLoader( '' ); + statBar.find('div').append( loader ); + + // Create unlock form and put info and status bars on the form + var unlockNonNodesForm = $( '
                  ' ); + unlockNonNodesForm.append( infoBar, statBar ); + + // Create 'Create an Unlock Script' fieldset + fs = $( '
                  ' ); + legend = $( 'Create an Unlock Script' ); + fs.append( legend ); + unlockNonNodesForm.append( fs ); + + // Create Script bar + var scriptBarId = 'unlockNonNodesScriptBar' + instance; + var scriptBar = createStatusBar(scriptBarId).hide(); + unlockNonNodesForm.append( scriptBar ); + + var createBtn = createButton( 'Create Script' ); + createBtn.css({ + 'width': '200px', + 'display': 'block' + }); + + createBtn.click(function() { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + // Get the SSH keys for a non-node + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'unlockshow;' + tgtNodes + ';script;', + msg : 'out=' + statBarId + ';scriptBar=' + scriptBarId +';cmd=unlock;tgt=' + tgtNodes + }, + + success : function(data) { + data = decodeRsp(data); + updateScriptBar(data); + } + }); + + // Show status bar + statBar.show(); + }); + + unlockNonNodesForm.append( createBtn ); + + // Create 'Unlock a system using the root password' Script fieldset + fs = $( '
                  ' ); + legend = $( 'Unlock a system using the root password' ); + fs.append( legend ); + unlockNonNodesForm.append( fs ); + + var vmAttr = $('
                  ' ); + fs.append($('
                  ')); + fs.append( vmAttr ); + + vmAttr.append( '
                  ' ); + vmAttr.append( '
                  ' ); + + /** + * Unlock button for non-nodes + */ + var unlockBtn = createButton('Unlock'); + unlockBtn.css({ + 'width': '80px', + 'display': 'block' + }); + + unlockBtn.click(function() { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + // If an ip and password is given + var ip = $('#' + newTabId + ' input[name=ip]').css('border', 'solid #BDBDBD 1px'); + var password = $( '#' + newTabId + ' input[name=password]').css('border', 'solid #BDBDBD 1px' ); + if ( password.val() && ip.val() ) { + $('#' + statBarId).find('img').show(); + // Setup SSH keys for a non-node + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'unlockbyip;' + tgtNodes + ';' + password.val() + ";" + ip.val(), + msg : 'out=' + statBarId + ';cmd=unlock;tgt=' + tgtNodes + }, + + success : function(data) { + data = decodeRsp(data); + updateStatusBar(data); + } + }); + + // Show status bar + statBar.show(); + } else { + // Show warning message + var warn = createWarnBar('Both ip address and password must be specified.'); + warn.prependTo($(this).parents('.ui-tabs-panel')); + password.css('border', 'solid #FF0000 1px'); + } + }); + + unlockNonNodesForm.append(unlockBtn); + + // Create 'SSH Key' fieldset + var sshKey = ''; + fs = $( '
                  ' ); + legend = $( 'xCAT Management Node Public Key' ); + fs.append( legend ); + unlockNonNodesForm.append( fs ); + + // Create key bar, hide on load + var keyBarId = 'unlockNonNodesKeyBar' + instance; + var keyBar = createStatusBar(keyBarId).hide(); + unlockNonNodesForm.append( keyBar ); + + // Generate tooltips + unlockNonNodesForm.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" + } + }); + + /** + * "Get Key" button + */ + var getBtn = createButton('Get Key'); + getBtn.css({ + 'width': '80px', + 'display': 'block' + }); + + getBtn.click(function() { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + // Get the SSH keys for a non-node + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'unlockshow;' + tgtNodes + ';key;', + msg : 'out=' + statBarId + ';keyBar=' + keyBarId +';cmd=unlock;tgt=' + tgtNodes + }, + + success : function(data) { + data = decodeRsp(data); + updateKeyBar(data); + } + }); + + // Show status bar + statBar.show(); + }); + + unlockNonNodesForm.append(getBtn); + + tab.add(newTabId, 'Unlock System', unlockNonNodesForm, true); + tab.select(newTabId); +} + + +/** + * Update key and status bar of a given tab + * + * @param data Data returned from HTTP request + */ +function updateKeyBar(data) { + // Get ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + var statBarId = args[0].replace('out=', ''); + var keyBarId = args[1].replace('keyBar=', ''); + var cmd = args[2].replace('cmd=', ''); + var tgts = args[3].replace('tgt=', '').split(','); + + $('#' + statBarId).find('img').hide(); + + // Extract the key portion and status portions from the response + var keyRespStart = rsp[0].indexOf(""); + var keyRespEnd = rsp[0].indexOf("");; + var keyOnly = rsp[0].substring( keyRespStart+9, keyRespEnd ); + var statLines = rsp[0].substring( 0, keyRespStart-1 ); + + if ( keyOnly.length > 0 ) { + // Expected response was returned, show it in the key bar. + var keyLines = keyOnly.split(/\n/); + for ( var i in keyLines ) { + $('#' + keyBarId).find( 'div' ).append( keyLines[i] ); + $('#' + keyBarId).find( 'div' ).append( '
                  ' ); + } + $('#' + keyBarId).show(); + + // Other lines from the response are shown in the Status bar. + if ( statLines.length > 0 ) { + prg = statLines.split(/\n/); + prg = writeRsp( prg, '' ); + $('#' + statBarId).find( 'div' ).append( prg ); + } + } else { + // Did not find the expected response, write the ajax response to status bar. + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + } + +} + + +/** + * Update the script and status bar of a given tab + * + * @param data Data returned from HTTP request + */ +function updateScriptBar(data) { + // Get ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + var statBarId = args[0].replace('out=', ''); + var scriptBarId = args[1].replace('scriptBar=', ''); + var cmd = args[2].replace('cmd=', ''); + var tgts = args[3].replace('tgt=', '').split(','); + + $('#' + statBarId).find('img').hide(); + + // Extract the key portion and status portions from the response + var scriptRespStart = rsp[0].indexOf(""); + var scriptRespEnd = rsp[0].indexOf("");; + var scriptOnly = rsp[0].substring( scriptRespStart+12, scriptRespEnd ); + var statLines = rsp[0].substring( 0, scriptRespStart-1 ); + + if ( scriptOnly.length > 0 ) { + // Expected response was returned, show it in the script bar along with the rest of the code. + var scriptLines = scriptOnly.split(/\n/); + for ( var i in scriptLines ) { + scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s\s\s+/gm, '        '); + scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s\s\s+/gm, '      '); + scriptLines[i] = scriptLines[i].replace(/^\s\s\s\s+/gm, '    '); + scriptLines[i] = scriptLines[i].replace(/^\s\s+/gm, '  '); + $('#' + scriptBarId).find( 'div' ).append( scriptLines[i] + '
                  ' ); + } + $('#' + scriptBarId).show(); + + // Other lines from the response are shown in the Status bar. + if ( statLines.length > 0 ) { + prg = statLines.split(/\n/); + prg = writeRsp( prg, '' ); + $('#' + statBarId).find( 'div' ).append( prg ); + } + } else { + // Did not find the expected response, write the ajax response to status bar. + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + } + +} + + +/** + * Load script page + * + * @param tgtNodes Targets to run script against + */ +function loadScriptPage(tgtNodes) { + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'scriptTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'scriptTab' + inst; + } + + // Create remote script form + var scriptForm = $('
                  '); + + // Create status bar + var barId = 'scriptStatusBar' + inst; + var statBar = createStatusBar(barId); + statBar.hide(); + var loader = createLoader('scriptLoader' + inst); + statBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('Load a script to run against this node range.'); + scriptForm.append(infoBar, statBar); + + // Create VM fieldset + var vmFS = $('
                  '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + scriptForm.append(vmFS); + + var vmAttr = $('
                  '); + vmFS.append($('
                  ')); + vmFS.append(vmAttr); + + // Create logs fieldset + var scriptFS = $('
                  '); + var scriptLegend = $('Script'); + scriptFS.append(scriptLegend); + scriptForm.append(scriptFS); + + var scriptAttr = $('
                  '); + scriptFS.append($('
                  ')); + scriptFS.append(scriptAttr); + + // Target node or group + var tgt = $('
                  '); + vmAttr.append(tgt); + + // Upload file + var upload = $('
                  '); + var label = $(''); + var file = $(''); + var subBtn = createButton('Load'); + upload.append(label, file, subBtn); + scriptAttr.append(upload); + + // Script + var script = $('
                  ').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/cmd.php', + dataType : 'json', + data : { + cmd : 'chdef', + tgt : '', + args : '-t;node;-o;' + node + ';usercomment=' + comments, + msg : 'out=nodesTab;tgt=' + node + }, + + success: function(data) { + data = decodeRsp(data); + showChdefOutput(data); + } + }); + + // 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; +} + +/** + * Create a tool tip for node status + * + * @return Tool tip + */ +function createStatusToolTip() { + // Create tooltip container + var toolTip = $('
                  ').css({ + 'width': '150px', + 'font-weight': 'normal' + }); + + // Create info text + var info = $('

                  ').css({ + 'white-space': 'normal' + }); + info.append('Click here to refresh the node status. To configure the xCAT monitor, '); + + // Create link to turn on xCAT monitoring + var monitorLnk = $('click here').css({ + 'color': '#58ACFA', + 'font-size': '10px' + }); + + // Open dialog to configure xCAT monitor + monitorLnk.bind('click', function(){ + // Check if xCAT monitor is enabled + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'monls', + tgt : '', + args : 'xcatmon', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + openConfXcatMon(data); + } + }); + }); + + info.append(monitorLnk); + toolTip.append(info); + + return toolTip; +} + +/** + * Create a tool tip for power status + * + * @return Tool tip + */ +function createPowerToolTip() { + // Create tooltip container + var toolTip = $('
                  Click here to refresh the power status
                  ').css({ + 'width': '150px', + 'white-space': 'normal', + 'font-weight': 'normal' + }); + return toolTip; +} + +/** + * Create a tool tip for monitoring status + * + * @return Tool tip + */ +function createMonitorToolTip() { + // Create tooltip container + var toolTip = $('
                  Click here to refresh the monitoring status
                  ').css({ + 'width': '150px', + 'white-space': 'normal', + 'font-weight': 'normal' + }); + return toolTip; +} + +/** + * Open dialog to configure xCAT monitor + * + * @param data Data returned from HTTP request + */ +function openConfXcatMon(data) { + // Create info bar + var info = createInfoBar('Configure the xCAT monitor. Select to enable or disable the monitor below.'); + var dialog = $('
                  '); + dialog.append(info); + + // Create status area + var statusArea = $('
                  ').css('padding-top', '10px'); + var label = $(''); + statusArea.append(label); + + // Get xCAT monitor status + var status = data.rsp[0]; + var buttons; + // If xCAT monitor is disabled + if (status.indexOf('not-monitored') > -1) { + status = $('Disabled').css('padding', '0px 5px'); + statusArea.append(status); + + // Create enable and cancel buttons + buttons = { + "Enable": function(){ + // Enable xCAT monitor + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'monstart', + tgt : '', + args : 'xcatmon', + msg : '' + }, + + success : function(data){ + data = decodeRsp(data); + openDialog('info', data.rsp[0]); + } + }); + $(this).dialog("close"); + }, + "Cancel": function(){ + $(this).dialog("close"); + } + }; + } else { + status = $('Enabled').css('padding', '0px 5px'); + statusArea.append(status); + + // Create disable and cancel buttons + buttons = { + "Disable": function(){ + // Disable xCAT monitor + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'monstop', + tgt : '', + args : 'xcatmon', + msg : '' + }, + + success : function(data){ + data = decodeRsp(data); + openDialog('info', data.rsp[0]); + } + }); + $(this).dialog("close"); + }, + "Cancel": function(){ + $(this).dialog("close"); + } + }; + } + + dialog.append(statusArea); + + // Open dialog + dialog.dialog({ + modal: true, + width: 500, + buttons: buttons + }); +} + +/** + * Show chdef output + * + * @param data Data returned from HTTP request + */ +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); +} + +/** + * Set node attributes + * + * @param data Data returned from HTTP request + */ +function setNodeAttrs(data) { + // Clear hash table containing definable node attributes + nodeAttrs = new Array(); + + // Get definable attributes + var attrs = data.rsp[2].split(/\n/); + + // Go through each line + var attr, key, descr; + for (var i in attrs) { + attr = attrs[i]; + + // If the line is not empty + if (attr) { + // If the line has the attribute name + if (attr.indexOf(':') && attr.indexOf(' ')) { + // Get attribute name and description + key = jQuery.trim(attr.substring(0, attr.indexOf(':'))); + descr = jQuery.trim(attr.substring(attr.indexOf(':') + 1)); + + // Remove arrow brackets + descr = descr.replace(new RegExp('<|>', 'g'), ''); + + // Set hash table where key = attribute name and value = description + nodeAttrs[key] = descr; + } else { + // Remove arrow brackets + attr = attr.replace(new RegExp('<|>', 'g'), ''); + + // Append description to hash table + nodeAttrs[key] = nodeAttrs[key] + '\n' + attr; + } + } // End of if + } // End of for +} + + +/** + * Load the discover z/VM virtual systems page + * + * @param tgtNode Target node to set properties + */ +function discoverVMNodes(tgtNodes) { + var fs, legend, htmlLine; + + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'discoverVMNodesTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'discoverVMNodesTab' + inst; + } + + // Open new tab + // Create set properties form + var discoverVMNodesForm = $('
                  '); + + // Create info bar + var infoBar = createInfoBar( 'Initiate, stop or query the status of z/VM node discovery. ' + + 'To initiate discovery, specify discovery parameters and click on the Discover button. ' + + 'To stop an on-going discovery related to a z/VM host, specify the host node name and '+ + 'click on the Stop button. ' + + 'To obtain the status of discovery for a particular host, specify the host node name and '+ + 'click on the Stop button.' + ); + discoverVMNodesForm.append(infoBar); + + // Create the status bar and hide it. + var statBarId = 'statusBar_' + newTabId; + //var statBar = $( '
                  ' ); + //discoverVMNodesForm.append( statBar ); + statBar = createStatusBar( statBarId ); + statBar.hide(); + discoverVMNodesForm.append( statBar ); + + // Create Host fieldset + fs = $('
                  '); + legend = $('z/VM Host'); + fs.append(legend); + discoverVMNodesForm.append(fs); + + // Target node or group + htmlLine = $('
                  '); + discoverVMNodesForm.append( htmlLine ); + + // Create Discovery Parameters fieldset + fs = $('
                  '); + legend = $('Discovery Parameters'); + fs.append( legend ); + discoverVMNodesForm.append( fs ); + + // Create an input for each definable attribute + var div, label, input, descr, value; + + // Define DefineTo radio buttons + div = $('
                  ').css( 'display', 'inline-block' ).css( 'vertical-align', 'top' ); + div.append( '' ); + div.append( '
                • xCAT and OpenStack
                • ' ); + div.append( '
                • xCAT only
                • ' ); + div.append( '
                • OpenStack only (only already discovered xCAT nodes)
                • ' ); + discoverVMNodesForm.append( div ); + discoverVMNodesForm.append( '
                  ' ); + + // Userid filter + divUserid = newTabId + "_divUserid"; + div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); + div.append( '' ); + div.append( '' ).css( 'margin-top', '5px' ); + discoverVMNodesForm.append( div ); + discoverVMNodesForm.append( '
                  ' ); + + // IP address filter + divIP = newTabId + "_divIP"; + div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); + div.append( '' ); + div.append( '' ).css( 'margin-top', '5px' ); + discoverVMNodesForm.append( div ); + discoverVMNodesForm.append( '
                  ' ); + + // Group name input + divGroup = newTabId + '_divGroup'; + div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); + div.append( '' ); + div.append( '' ).css( 'margin-top', '5px' ); + discoverVMNodesForm.append( div ); + discoverVMNodesForm.append( '
                  ' ); + + // Node Name Format input + divNodename = newTabId + '_divNodename'; + div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); + div.append( '' ); + div.append( '' ).css( 'margin-top', '5px' ); + discoverVMNodesForm.append( div ); + discoverVMNodesForm.append( '
                  ' ); + discoverVMNodesForm.find('#' + divNodename).hide(); + + // OpenStack operand input + divOpenStackOps = newTabId + '_divOpenStackOps'; + div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ); + div.append( '' ); + div.append( '' ).css( 'margin-top', '5px' ); + div.append( '
                  ' ); + div.append( '' ); + div.append( '' ).css( 'margin-top', '5px' ); + discoverVMNodesForm.append( div ); + discoverVMNodesForm.append( '
                  ' ); + + // Define Verbose radio buttons + div = $('
                  ').css( 'display', 'inline-table' ).css( 'vertical-align', 'top' ).css( 'text-align', 'top' ); + div.append( '' ); + div.append( '
                • Normal response, showing only important information
                • ' ); + div.append( '
                • Verbose response, normal response plus additional information (e.g. reason a system is ignored)
                • ' ); + discoverVMNodesForm.append( div ); + discoverVMNodesForm.append( '
                  ' ); + + // Generate tooltips + discoverVMNodesForm.find('div input[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + } + }); + + // Show appropriate input fields for defineto choices. + discoverVMNodesForm.change(function(){ + var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val(); + if ( defineTo == 'both' ) { + discoverVMNodesForm.find('#' + divUserid).show(); + discoverVMNodesForm.find('#' + divIP).show(); + discoverVMNodesForm.find('#' + divGroup).show(); + discoverVMNodesForm.find('#' + divOpenStackOps).show(); + discoverVMNodesForm.find('#' + divNodename).hide(); + } else if ( defineTo == 'xcatonly' ) { + discoverVMNodesForm.find('#' + divUserid).show(); + discoverVMNodesForm.find('#' + divIP).show(); + discoverVMNodesForm.find('#' + divGroup).show(); + discoverVMNodesForm.find('#' + divOpenStackOps).hide(); + discoverVMNodesForm.find('#' + divNodename).show(); + } else if ( defineTo == 'openstackonly' ) { + discoverVMNodesForm.find('#' + divUserid).hide(); + discoverVMNodesForm.find('#' + divIP).hide(); + discoverVMNodesForm.find('#' + divGroup).hide(); + discoverVMNodesForm.find('#' + divOpenStackOps).show(); + discoverVMNodesForm.find('#' + divNodename).hide(); + } + }); + + + // Discover nodes button action + var discoverBtn = createButton('Discover'); + discoverBtn.click(function() { + var argList = ''; + var filter = ''; + + var hosts = $(this).parent().find('input[name=hosts]').val(); + if ( hosts != '' ) { + argList = 'zvmhost=' + hosts; + } + + var defineTo = $(this).parent().find('input[name="defineTo"]:checked').val(); + argList = argList + '||defineto=' + defineTo; + + var verbose = $(this).parent().find('input[name="verbose"]:checked').val(); + if ( verbose == 'yes' ) { + argList = argList + '||--verbose'; + } + + var useridFilter = $(this).parent().find('input[name=useridFilter]').val(); + if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( useridFilter != '' )) { + argList = argList + '||useridfilter=' + useridFilter; + } + + var ipFilter = $(this).parent().find('input[name=ipFilter]').val(); + if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( ipFilter != '' )) { + argList = argList + '||ipfilter=' + ipFilter; + } + + var group = $(this).parent().find('input[name=group]').val(); + if (( defineTo == 'both' || defineTo == 'xcatonly' ) && ( group != '' )) { + argList = argList + '||groups=' + group; + } + + var nodeNameFmt = $(this).parent().find('input[name=nodeNameFmt]').val(); + if ( defineTo == 'xcatonly' && nodeNameFmt != '' ) { + argList = argList + '||nodenameformat=' + nodeNameFmt; + } + + var openStackProj = $(this).parent().find('input[name=openStackProj]').val(); + var openStackUser = $(this).parent().find('input[name=openStackUser]').val(); + if ((( defineTo == 'both' ) || ( defineTo == 'openstackonly' )) && + (( openStackProj != '' ) || ( openStackUser != '' ))) { + if ( openStackProj != '' ) { + osArgs = '--project ' + openStackProj; + } else { + osArgs = ''; + } + if ( openStackUser != '' ) { + if ( osArgs != '' ) { + osArgs = osArgs + ' --user ' + openStackUser; + } else { + osArgs = '--user ' + openStackUser; + } + } + argList = argList + "||openstackoperands='" + osArgs + "'"; + } + + var out = $('

                  '); + out.append( 'Starting node discovery...' ); + out.append( '
                  ' ); + out.append( 'If node discovery is a short running task then its response will follow. If, however, the time it takes to complete discovery exceeds the http request timeout of a few minutes then the discovery response will not be returned to the browser. The status and list buttons can be used to obtained status on the discovery and see what systems have been discovered.' ); + $( '#' + statBarId ).find( 'div' ).append( out ); + statBar.show(); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodediscoverstart', + tgt : '', + args : argList, + att : '', + msg : statBarId + }, + success: function(data) { + data = decodeRsp(data); + updateDiscoverStatusBar( data, 1 ); + } + }); + + }); + discoverVMNodesForm.append(discoverBtn); + + // Status button + var statusBtn = createButton('Status'); + statusBtn.click( function() { + var hosts = $(this).parent().find('input[name=hosts]').val(); + var out = $('

                  '); + out.append( 'Querying status for discovery on ' + hosts + '...' ); + out.append( '
                  ' ); + $( '#' + statBarId ).find( 'div' ).append( out ); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodediscoverstatus', + tgt : '', + args : '--zvmhost||' + hosts, + att : '', + msg : statBarId + }, + success: function(data) { + data = decodeRsp(data); + updateDiscoverStatusBar( data, 1 ); + } + }); + + }); + discoverVMNodesForm.append( statusBtn ); + + // List button + var listBtn = createButton('List'); + listBtn.click( function() { + var hosts = $(this).parent().find('input[name=hosts]').val(); + var out = $('

                  '); + out.append( 'Listing systems discovered by the latest discovery on ' + hosts + '...' ); + out.append( '
                  ' ); + $( '#' + statBarId ).find( 'div' ).append( out ); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodediscoverls', + tgt : '', + args : '-t||zvm||--zvmhost||' + hosts, + att : '', + msg : statBarId + }, + success: function(data) { + data = decodeRsp(data); + updateDiscoverStatusBar( data, 1 ); + } + }); + }); + discoverVMNodesForm.append( listBtn ); + + // Stop button + var stopBtn = createButton('Stop'); + stopBtn.click(function() { + var hosts = $(this).parent().find('input[name=hosts]').val(); + var out = $('

                  '); + out.append( 'Stopping discovery on ' + hosts + '...' ); + out.append( '
                  ' ); + $( '#' + statBarId ).find( 'div' ).append( out ); + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodediscoverstop', + tgt : '', + args : '--zvmhost||' + hosts, + att : '', + msg : statBarId + }, + success: function(data) { + data = decodeRsp(data); + updateDiscoverStatusBar( data, 1 ); + } + }); + }); + discoverVMNodesForm.append( stopBtn ); + + // Append to discover tab + tab.add(newTabId, 'Discover', discoverVMNodesForm, true); + + // Select new tab + tab.select(newTabId); +} + + +/** + * Update discovery status bar + * + * @param data Data returned from HTTP request + */ +function updateDiscoverStatusBar( data, preformatted ) { + var statBarId = data.msg; + var rsp = data.rsp; + var statBar = $( '#' + statBarId ); + + // Go through response to make it readable in the status bar. + var out = $('

                  '); + for ( var i in rsp ) { + if ( preformatted == 1 ) { + out.append( '
                  ' + rsp[i] + '
                  ' ); + } else { + out.append( rsp[i] + '
                  ' ); + } + } + + // Write response to status bar and show the bar. + $( '#' + statBarId ).find( 'div' ).append( out ); + statBar.show(); +} + + +/** + * Load set node properties page + * + * @param tgtNode Target node to set properties + */ +function editNodeProps(tgtNode) { + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'editPropsTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'editPropsTab' + inst; + } + + // Open new tab + // Create set properties form + var editPropsForm = $('
                  '); + + // Create info bar + var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.'); + editPropsForm.append(infoBar); + + // Create an input for each definable attribute + var div, label, input, descr, value; + // Set node attribute + origAttrs[tgtNode]['node'] = tgtNode; + for (var key in nodeAttrs) { + // If an attribute value exists + if (origAttrs[tgtNode][key]) { + // Set the value + value = origAttrs[tgtNode][key]; + } else { + value = ''; + } + + // Create label and input for attribute + div = $('
                  ').css('display', 'inline-table'); + label = $('').css('vertical-align', 'middle'); + input = $('').css('margin-top', '5px'); + + // Change border to blue onchange + input.bind('change', function(event) { + $(this).css('border-color', 'blue'); + }); + + div.append(label); + div.append(input); + editPropsForm.append(div); + } + + // Change style for last division + div.css({ + 'display': 'block', + 'margin': '0px 0px 10px 0px' + }); + + // Generate tooltips + editPropsForm.find('div input[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + } + }); + + // Save changes + var saveBtn = createButton('Save'); + saveBtn.click(function() { + // Get all inputs + var inputs = $('#' + newTabId + ' input'); + + // Go through each input + var args = ''; + var attrName, attrVal; + inputs.each(function(){ + // If the border color is blue + if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') { + // Change border color back to normal + $(this).css('border-color', ''); + + // Get attribute name and value + attrName = $(this).parent().find('label').text().replace(':', ''); + attrVal = $(this).val(); + + // Build argument string + if (args) { + // Handle subsequent arguments + args += ';' + attrName + '=' + attrVal; + } else { + // Handle the 1st argument + args += attrName + '=' + attrVal; + } + } + }); + + // Send command to change node attributes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chdef', + tgt : '', + args : '-t;node;-o;' + tgtNode + ';' + args, + msg : 'out=' + newTabId + ';tgt=' + tgtNode + }, + + success: function(data) { + data = decodeRsp(data); + showChdefOutput(data); + } + }); + }); + editPropsForm.append(saveBtn); + + // Cancel changes + var cancelBtn = createButton('Cancel'); + cancelBtn.click(function() { + // Close the tab + tab.remove($(this).parent().parent().attr('id')); + }); + editPropsForm.append(cancelBtn); + + // Append to discover tab + tab.add(newTabId, 'Edit', editPropsForm, true); + + // Select new tab + tab.select(newTabId); +} + +/** + * Open set node attributes dialog + */ +function openSetAttrsDialog() { + // Open new tab + // Create set properties form + var setPropsForm = $('
                  '); + + // Create info bar + var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.'); + setPropsForm.append(infoBar); + + // Create an input for each definable attribute + var div, label, input, descr, value; + for (var key in nodeAttrs) { + value = ''; + + // Create label and input for attribute + div = $('
                  ').css('display', 'inline'); + label = $('').css('vertical-align', 'middle'); + input = $('').css('margin-top', '5px'); + + // Change border to blue onchange + input.bind('change', function(event) { + $(this).css('border-color', 'blue'); + }); + + div.append(label); + div.append(input); + setPropsForm.append(div); + } + + // Change style for last division + div.css({ + 'display': 'block', + 'margin': '0px 0px 10px 0px' + }); + + // Generate tooltips + setPropsForm.find('div input[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Enable vertical scroll + setPropsForm.css('overflow', 'auto'); + + // Open form as a dialog + setPropsForm.dialog({ + title: 'Set attributes', + modal: true, + close: function(){ + $(this).remove(); + }, + height: 400, + width: 800, + buttons: { + "Save": function() { + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get all inputs + var inputs = $(this).find('input'); + + // Go through each input + var args = ''; + var tgtNode, attrName, attrVal; + inputs.each(function(){ + // If the border color is blue + if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') { + // Change border color back to normal + $(this).css('border-color', ''); + + // Get attribute name and value + attrName = $(this).parent().find('label').text().replace(':', ''); + attrVal = $(this).val(); + + // Get node name + if (attrName == 'node') { + tgtNode = attrVal; + } else { + // Build argument string + if (args) { + // Handle subsequent arguments + args += ';' + attrName + '=' + attrVal; + } else { + // Handle the 1st argument + args += attrName + '=' + attrVal; + } + } + } + }); + + // Send command to change node attributes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chdef', + tgt : '', + args : '-t;node;-o;' + tgtNode + ';' + args, + msg : 'node=' + tgtNode + }, + + /** + * Show results + * + * @param data + * Data returned from HTTP request + * @return Nothing + */ + success: function(data) { + // Get output + data = decodeRsp(data); + var out = data.rsp; + var node = data.msg.replace('node=', ''); + + // Go through output and append to paragraph + var msg = ''; + for (var i in out) { + if (!msg) { + msg = node + ': ' + out[i]; + } else { + msg += '
                  ' + node + ': ' + out[i]; + } + } + + openDialog('info', msg); + } + }); + + // Close dialog + $(this).dialog( "close" ); + }, + "Cancel": function(){ + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Turn on monitoring for a given node + * + * @param node Node to monitor on or off + * @param monitor Monitor state, on or off + */ +function monitorNode(node, monitor) { + // Show ganglia loader + var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); + gangliaCol.find('img').show(); + + if (monitor == 'on') { + // Append loader to warning bar + var warningBar = $('#nodesTab').find('.ui-state-error p'); + if (warningBar.length) { + warningBar.append(createLoader('')); + } + + if (node) { + // Check if ganglia RPMs are installed + $.ajax( { + url : 'lib/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 + */ + success : function(data) { + // Get response + data = decodeRsp(data); + 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/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'gangliastart;' + data.msg + ';-r', + msg : data.msg + }, + + success : function(data) { + data = decodeRsp(data); + // Remove any warnings + $('#nodesTab').find('.ui-state-error').remove(); + + // Update datatable + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'gangliastatus;' + data.msg, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadGangliaStatus(data); + } + }); + } + }); + } // End of if (warn) + } // End of function(data) + }); + } else { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'gangliastart', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + // Remove any warnings + $('#nodesTab').find('.ui-state-error').remove(); + } + }); + } // End of if (node) + } else { + var args; + if (node) { + args = 'gangliastop;' + node + ';-r'; + } else { + args = 'gangliastop'; + } + + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : args, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + // Hide ganglia loader + var gangliaCol = $('#' + nodesTableId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); + gangliaCol.find('img').hide(); + } + }); + } +} + +/** + * Install Ganglia on a given node + * + * @param node Node to install Ganglia on + */ +function installGanglia(node) { + var iframe = createIFrame('lib/cmd.php?cmd=webrun&tgt=&args=installganglia;' + node + '&msg=' + node + '&opts=flush'); + iframe.prependTo($('#nodesTab')); + + // Turn on Ganglia for node + monitorNode(node, 'on'); +} + +/** + * After nodes are loaded, load more information based on different hardware architectures + * + * @param group Group name + */ +function advancedLoad(group){ + var tempIndex = 0; + var tableHeaders = $('#' + nodesTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); + var colNameHash = new Object(); + var colName = ''; + var archCol = 0, hcpCol = 0; + + // Find out the column name and their index + for (tempIndex = 0; tempIndex < tableHeaders.size(); tempIndex++){ + var header = tableHeaders.eq(tempIndex); + // Skip headers that are links, e.g. status, power, and monitor + if (header.find('a').size() > 0){ + continue; + } + + colName = header.text(); + + if (colName) { + colNameHash[colName] = tempIndex; + } + } + + // If there is no arch column, exit because you cannot distinguish hardware type + if (!colNameHash['arch']) { + return; + } + + if (!colNameHash['hcp']) { + return; + } + archCol = colNameHash['arch']; + hcpCol = colNameHash['hcp']; + + // Get hardware control point + var rows = $('#' + nodesTableId + ' tbody tr'); + var hcps = new Object(); + var rowsNum = rows.size(); + for (var j = 0; j < rowsNum; j++) { + var val = rows.eq(j).find('td').eq(hcpCol).html(); + var archval = rows.eq(j).find('td').eq(archCol).html(); + if (-1 == archval.indexOf('390')){ + continue; + } + hcps[val] = 1; + } + + if (Object.keys(hcps).length == 0) { + openDialog('warn', "No node found with hcp column filled in and 390 arch!"); + return; + } + // Get Nodes info bar + //var nodeInfoBar = getNodesTabInfoBar(); + //nodeInfoBar.append("\nEntering Advanced Load...\n") + + var args; + var shortzHcps = new Array(); + var zhcpHash = new Object(); + for (var h in hcps) { + // Get node without domain name + args = h.split('.'); + + if (!zhcpHash[args[0]]) { + + shortzHcps.push(args[0]); + zhcpHash[args[0]] = 1; + + // If there are no disk pools or network names cookie for this hcp + if (!$.cookie('xcat_' + args[0] + 'diskpools') || !$.cookie('xcat_' + args[0] + 'networks')) { + // Check if SMAPI is online + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsvm', + tgt : args[0], + args : '', + msg : 'group=' + group + ';hcp=' + args[0] + }, + + // Load hardware control point specific info + // Get disk pools and network names + success : function(data) { + data = decodeRsp(data); + loadHcpInfo(data); + } + }); + } + } + } // End of for + + // Save zHCPs as a cookie + setzHcpCookies(shortzHcps); + + // Retrieve z/VM hypervisors and their zHCPs + if (!$.cookie('xcat_zvms')) { + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webportal', + tgt : '', + args : 'lszvm', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setzVMCookies(data); + } + }); + } +} + +/** + * Jump to provision page on-click + * + * @param tgtNodes Target nodes + */ +function jump2Provision(tgtNodes){ + var nodeArray = tgtNodes.split(','); + var nodeName = ''; + var index = 0; + var archType = ''; + var errorMsg = ''; + var master = ''; + var tftpserver = ''; + var nfsserver = ''; + var diaDiv = $('
                  '); + + // Check the first node's arch type + for (index in nodeArray){ + nodeName = nodeArray[index]; + + // Skip if node does not have arch + if (!origAttrs[nodeName]['arch']){ + errorMsg = 'Nodes should have arch defined! '; + break; + } + + if (index == 0) { + archType = origAttrs[nodeName]['arch']; + } + + // Skip if nodes do not have same arch + if (archType != origAttrs[nodeName]['arch']){ + errorMsg = 'Nodes should belong to the same arch!
                  '; + break; + } + } + + // Skip if nodes do not have MAC address + for (index in nodeArray){ + if (!origAttrs[nodeName]['mac'] || !origAttrs[nodeName]['ip']){ + errorMsg += 'Nodes should have the IP and MAC addresses defined!
                  '; + break; + } + } + + if (archType.indexOf('390') != -1) { + errorMsg += 'Please use the provision page'; + } + + // Open dialog to show error message + if (errorMsg){ + diaDiv.append(createWarnBar(errorMsg)); + diaDiv.dialog({ + modal: true, + close: function(){ + $(this).remove(); + }, + width: 400, + buttons: { + 'Close': function(){ + $(this).dialog('destroy'); + } + } + }); + + return; + } + + if (origAttrs[nodeName]['xcatmaster']) { + master = origAttrs[nodeName]['xcatmaster']; + } + + if (origAttrs[nodeName]['tftpserver']) { + tftpserver = origAttrs[nodeName]['tftpserver']; + } + + if (origAttrs[nodeName]['nfsserver']) { + nfsserver = origAttrs[nodeName]['nfsserver']; + } + + window.location.href = 'provision.php?nodes=' + tgtNodes + '&arch=' + archType + '&master=' + master + + '&tftpserver=' + tftpserver + '&nfsserver=' + nfsserver; +} diff --git a/xCAT-UI/js/nodes/nodeset.js b/xCAT-UI/js/nodes/nodeset.js index c1b2acfe8..87d84ba1e 100644 --- a/xCAT-UI/js/nodes/nodeset.js +++ b/xCAT-UI/js/nodes/nodeset.js @@ -1,296 +1,308 @@ -/** - * Load nodeset page - * - * @param tgtNodes Targets to run nodeset against - */ -function loadNodesetPage(tgtNodes) { - // Get OS images - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : 'osimage', - msg : '' - }, - - success : setOSImageCookies - }); - - // Get nodes tab - var tab = getNodesTab(); - - // Generate new tab ID - var inst = 0; - var tabId = 'nodesetTab' + inst; - while ($('#' + tabId).length) { - // If one already exists, generate another one - inst = inst + 1; - tabId = 'nodesetTab' + inst; - } - - // Create nodeset form - var nodesetForm = $('
                  '); - - // Create status bar - var statBarId = 'nodesetStatusBar' + inst; - var statBar = createStatusBar(statBarId).hide(); - - // Create loader - var loader = createLoader('nodesetLoader'); - statBar.find('div').append(loader); - - // Create info bar - var infoBar = createInfoBar('Set the boot state for a node range'); - nodesetForm.append(statBar, infoBar); - - // Create VM fieldset - var vmFS = $('
                  '); - var vmLegend = $('Virtual Machine'); - vmFS.append(vmLegend); - nodesetForm.append(vmFS); - - var vmAttr = $('
                  '); - vmFS.append($('
                  ')); - vmFS.append(vmAttr); - - // Create options fieldset - var imageFS = $('
                  '); - var imageLegend = $('Image'); - imageFS.append(imageLegend); - nodesetForm.append(imageFS); - - var imageAttr = $('
                  '); - imageFS.append($('
                  ')); - imageFS.append(imageAttr); - - // Create target node or group - var tgt = $('
                  '); - vmAttr.append(tgt); - - // Create boot type drop down - var type = $('
                  '); - var typeLabel = $(''); - var typeSelect = $(''); - typeSelect.append('' - + '' - + '' - ); - type.append(typeLabel); - type.append(typeSelect); - imageAttr.append(type); - - // Create operating system image input - var os = $('
                  '); - var osLabel = $(''); - var osSelect = $(''); - osSelect.append($('')); - - var imageNames = $.cookie('xcat_imagenames').split(','); - if (imageNames) { - imageNames.sort(); - for (var i in imageNames) { - osSelect.append($('')); - } - } - os.append(osLabel); - os.append(osSelect); - imageAttr.append(os); - - // Generate tooltips - nodesetForm.find('div input[title],select').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" - } - }); - - /** - * Ok - */ - var okBtn = createButton('Ok'); - okBtn.css({ - 'width': '80px', - 'display': 'block' - }); - okBtn.bind('click', function(event) { - // Remove any warning messages - $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); - - // Check state, OS, arch, and profile - var ready = true; - var inputs = $('#' + tabId + ' input'); - for ( var i = 0; i < inputs.length; i++) { - if (!inputs.eq(i).val() && inputs.eq(i).attr('name') != 'diskPw') { - inputs.eq(i).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - inputs.eq(i).css('border', 'solid #BDBDBD 1px'); - } - } - - if (ready) { - // Get nodes - var tgts = $('#' + tabId + ' input[name=target]').val(); - // Get boot type - var type = $('#' + tabId + ' select[id=bootType]').val(); - // Get operating system image - var os = $('#' + tabId + ' select[name=os]').val(); - - // Disable all inputs, selects, and Ok button - inputs.attr('disabled', 'disabled'); - $('#' + tabId + ' select').attr('disabled', 'disabled'); - $(this).attr('disabled', 'true'); - - /** - * (1) Set the OS, arch, and profile - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeadd', - tgt : '', - args : tgts + ';noderes.netboot=' + type, - msg : 'cmd=nodeadd;inst=' + inst - }, - - success : updateNodesetStatus - }); - - // Show status bar - statBar.show(); - } else { - // Show warning message - var warn = createWarnBar('You are missing some values!'); - warn.prependTo($(this).parents('.ui-tabs-panel')); - } - }); - nodesetForm.append(okBtn); - - // Append to discover tab - tab.add(tabId, 'Nodeset', nodesetForm, true); - - // Select new tab - tab.select(tabId); -} - -/** - * Update nodeset status - * - * @param data Data returned from HTTP request - */ -function updateNodesetStatus(data) { - // Get ajax response - var rsp = data.rsp; - var args = data.msg.split(';'); - var cmd = args[0].replace('cmd=', ''); - - // Get nodeset instance - var inst = args[1].replace('inst=', ''); - // Get status bar ID - var statBarId = 'nodesetStatusBar' + inst; - // Get tab ID - var tabId = 'nodesetTab' + inst; - - // Get nodes - var tgts = $('#' + tabId + ' input[name=target]').val(); - // Get operating system image - var os = $('#' + tabId + ' select[name=os]').val(); - - /** - * (2) Update /etc/hosts - */ - if (cmd == 'nodeadd') { - if (rsp.length) { - $('#' + statBarId).find('img').hide(); - $('#' + statBarId).find('div').append('
                  (Error) Failed to create node definition
                  '); - } else { - // Create target nodes string - var tgtNodesStr = ''; - var nodes = tgts.split(','); - - // Loop through each node - for ( var i in nodes) { - // If it is the 1st and only node - if (i == 0 && i == nodes.length - 1) { - tgtNodesStr += nodes[i]; - } - // If it is the 1st node of many nodes - else if (i == 0 && i != nodes.length - 1) { - // Append a comma to the string - tgtNodesStr += nodes[i] + ', '; - } else { - // If it is the last node - if (i == nodes.length - 1) { - // Append nothing to the string - tgtNodesStr += nodes[i]; - } else { - // Append a comma to the string - tgtNodesStr += nodes[i] + ', '; - } - } - } - - $('#' + statBarId).find('div').append('
                  Node definition created for ' + tgtNodesStr + '
                  '); - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'makehosts', - tgt : '', - args : '', - msg : 'cmd=makehosts;inst=' + inst - }, - - success : updateNodesetStatus - }); - } - } - - /** - * (4) Update DNS - */ - else if (cmd == 'makehosts') { - // If no output, no errors occurred - if (rsp.length) { - $('#' + statBarId).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); - } else { - $('#' + statBarId).find('div').append('
                  /etc/hosts updated
                  '); - } - - // Go straight to prepare node for boot - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodeset', - tgt : tgts, - args : 'osimage=' + os, - msg : 'cmd=nodeset;inst=' + inst - }, - - success : updateNodesetStatus - }); - } - - /** - * (5) Boot node from network - */ - else if (cmd == 'nodeset') { - // Write ajax response to status bar - var prg = writeRsp(rsp, ''); - $('#' + statBarId).find('div').append(prg); - - // Hide loader - $('#' + statBarId).find('img').hide(); - } +/** + * Load nodeset page + * + * @param tgtNodes Targets to run nodeset against + */ +function loadNodesetPage(tgtNodes) { + // Get OS images + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'osimage', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setOSImageCookies(data); + } + }); + + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var tabId = 'nodesetTab' + inst; + while ($('#' + tabId).length) { + // If one already exists, generate another one + inst = inst + 1; + tabId = 'nodesetTab' + inst; + } + + // Create nodeset form + var nodesetForm = $('
                  '); + + // Create status bar + var statBarId = 'nodesetStatusBar' + inst; + var statBar = createStatusBar(statBarId).hide(); + + // Create loader + var loader = createLoader('nodesetLoader'); + statBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('Set the boot state for a node range'); + nodesetForm.append(statBar, infoBar); + + // Create VM fieldset + var vmFS = $('
                  '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + nodesetForm.append(vmFS); + + var vmAttr = $('
                  '); + vmFS.append($('
                  ')); + vmFS.append(vmAttr); + + // Create options fieldset + var imageFS = $('
                  '); + var imageLegend = $('Image'); + imageFS.append(imageLegend); + nodesetForm.append(imageFS); + + var imageAttr = $('
                  '); + imageFS.append($('
                  ')); + imageFS.append(imageAttr); + + // Create target node or group + var tgt = $('
                  '); + vmAttr.append(tgt); + + // Create boot type drop down + var type = $('
                  '); + var typeLabel = $(''); + var typeSelect = $(''); + typeSelect.append('' + + '' + + '' + ); + type.append(typeLabel); + type.append(typeSelect); + imageAttr.append(type); + + // Create operating system image input + var os = $('
                  '); + var osLabel = $(''); + var osSelect = $(''); + osSelect.append($('')); + + var imageNames = $.cookie('xcat_imagenames').split(','); + if (imageNames) { + imageNames.sort(); + for (var i in imageNames) { + osSelect.append($('')); + } + } + os.append(osLabel); + os.append(osSelect); + imageAttr.append(os); + + // Generate tooltips + nodesetForm.find('div input[title],select').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" + } + }); + + /** + * Ok + */ + var okBtn = createButton('Ok'); + okBtn.css({ + 'width': '80px', + 'display': 'block' + }); + okBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + // Check state, OS, arch, and profile + var ready = true; + var inputs = $('#' + tabId + ' input'); + for ( var i = 0; i < inputs.length; i++) { + if (!inputs.eq(i).val() && inputs.eq(i).attr('name') != 'diskPw') { + inputs.eq(i).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + inputs.eq(i).css('border', 'solid #BDBDBD 1px'); + } + } + + if (ready) { + // Get nodes + var tgts = $('#' + tabId + ' input[name=target]').val(); + // Get boot type + var type = $('#' + tabId + ' select[id=bootType]').val(); + // Get operating system image + var os = $('#' + tabId + ' select[name=os]').val(); + + // Disable all inputs, selects, and Ok button + inputs.attr('disabled', 'disabled'); + $('#' + tabId + ' select').attr('disabled', 'disabled'); + $(this).attr('disabled', 'true'); + + /** + * (1) Set the OS, arch, and profile + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeadd', + tgt : '', + args : tgts + ';noderes.netboot=' + type, + msg : 'cmd=nodeadd;inst=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateNodesetStatus(data); + } + }); + + // Show status bar + statBar.show(); + } else { + // Show warning message + var warn = createWarnBar('You are missing some values!'); + warn.prependTo($(this).parents('.ui-tabs-panel')); + } + }); + nodesetForm.append(okBtn); + + // Append to discover tab + tab.add(tabId, 'Nodeset', nodesetForm, true); + + // Select new tab + tab.select(tabId); +} + +/** + * Update nodeset status + * + * @param data Data returned from HTTP request + */ +function updateNodesetStatus(data) { + // Get ajax response + var rsp = data.rsp; + var args = data.msg.split(';'); + var cmd = args[0].replace('cmd=', ''); + + // Get nodeset instance + var inst = args[1].replace('inst=', ''); + // Get status bar ID + var statBarId = 'nodesetStatusBar' + inst; + // Get tab ID + var tabId = 'nodesetTab' + inst; + + // Get nodes + var tgts = $('#' + tabId + ' input[name=target]').val(); + // Get operating system image + var os = $('#' + tabId + ' select[name=os]').val(); + + /** + * (2) Update /etc/hosts + */ + if (cmd == 'nodeadd') { + if (rsp.length) { + $('#' + statBarId).find('img').hide(); + $('#' + statBarId).find('div').append('
                  (Error) Failed to create node definition
                  '); + } else { + // Create target nodes string + var tgtNodesStr = ''; + var nodes = tgts.split(','); + + // Loop through each node + for ( var i in nodes) { + // If it is the 1st and only node + if (i == 0 && i == nodes.length - 1) { + tgtNodesStr += nodes[i]; + } + // If it is the 1st node of many nodes + else if (i == 0 && i != nodes.length - 1) { + // Append a comma to the string + tgtNodesStr += nodes[i] + ', '; + } else { + // If it is the last node + if (i == nodes.length - 1) { + // Append nothing to the string + tgtNodesStr += nodes[i]; + } else { + // Append a comma to the string + tgtNodesStr += nodes[i] + ', '; + } + } + } + + $('#' + statBarId).find('div').append('
                  Node definition created for ' + tgtNodesStr + '
                  '); + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'makehosts', + tgt : '', + args : '', + msg : 'cmd=makehosts;inst=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateNodesetStatus(data); + } + }); + } + } + + /** + * (4) Update DNS + */ + else if (cmd == 'makehosts') { + // If no output, no errors occurred + if (rsp.length) { + $('#' + statBarId).find('div').append('
                  (Error) Failed to update /etc/hosts
                  '); + } else { + $('#' + statBarId).find('div').append('
                  /etc/hosts updated
                  '); + } + + // Go straight to prepare node for boot + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodeset', + tgt : tgts, + args : 'osimage=' + os, + msg : 'cmd=nodeset;inst=' + inst + }, + + success : function(data) { + data = decodeRsp(data); + updateNodesetStatus(data); + } + }); + } + + /** + * (5) Boot node from network + */ + else if (cmd == 'nodeset') { + // Write ajax response to status bar + var prg = writeRsp(rsp, ''); + $('#' + statBarId).find('div').append(prg); + + // Hide loader + $('#' + statBarId).find('img').hide(); + } } \ No newline at end of file diff --git a/xCAT-UI/js/nodes/physical.js b/xCAT-UI/js/nodes/physical.js index e8df2d4c8..24b010c8c 100644 --- a/xCAT-UI/js/nodes/physical.js +++ b/xCAT-UI/js/nodes/physical.js @@ -1,933 +1,935 @@ -var bpaList; -var fspList; -var lparList; -var bladeList; -var rackList; -var unknownList; -var graphicalNodeList; -var selectNode; - -/** - * Get all nodes useful attributes from remote server - * - * @param dataTypeIndex The index in the array which contains attributes we need. - * @param attrNullNode The target node list for this attribute - */ -function initGraphicalData() { - $('#graphTab').append(createLoader()); - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'graph', - msg : '' - }, - success : function(data) { - if (!data.rsp[0]) { - return; - } - extractGraphicalData(data.rsp[0]); - getNodesAndDraw(); - } - }); -} - -/** - * Extract all nodes userful data into a hash, which will be used for creating graphical - * - * @param data The response from xCAT command 'nodels all nodetype.nodetype ppc.parent ...' - * @return nodes list for next time query - */ -function extractGraphicalData(data) { - var nodes = data.split(';'); - var attrs; - var nodeName; - - // Extract useful info into tempList - for (var i = 0; i < nodes.length; i++) { - attrs = nodes[i].split(':'); - nodeName = attrs[0]; - if (undefined == graphicalNodeList[nodeName]) { - graphicalNodeList[nodeName] = new Object(); - } - - graphicalNodeList[nodeName]['type'] = attrs[1].toLowerCase(); - switch (attrs[1].toLowerCase()) { - case 'cec': - case 'frame': - case 'lpar': - case 'lpar,osi': - case 'osi,lpar': - graphicalNodeList[nodeName]['parent'] = attrs[2]; - graphicalNodeList[nodeName]['mtm'] = attrs[3]; - graphicalNodeList[nodeName]['status'] = attrs[4]; - break; - case 'blade': - graphicalNodeList[nodeName]['mpa'] = attrs[2]; - graphicalNodeList[nodeName]['unit'] = attrs[3]; - graphicalNodeList[nodeName]['status'] = attrs[4]; - break; - case 'systemx': - graphicalNodeList[nodeName]['rack'] = attrs[2]; - graphicalNodeList[nodeName]['unit'] = attrs[3]; - graphicalNodeList[nodeName]['mtm'] = attrs[4]; - graphicalNodeList[nodeName]['status'] = attrs[5]; - break; - default: - break; - } - } -} - -function createPhysicalLayout(nodeList) { - var flag = false; - - // When the graphical layout is shown, do not need to redraw - if (1 < $('#graphTab').children().length) { - return; - } - - // Save the new selected nodes - if (graphicalNodeList) { - for (var i in graphicalNodeList) { - flag = true; - break; - } - } - - bpaList = new Object(); - fspList = new Object(); - lparList = new Object(); - bladeList = new Object(); - selectNode = new Object(); - rackList = new Object(); - unknownList = new Array(); - - // There is no graphical data, get the info now - if (!flag) { - graphicalNodeList = new Object(); - initGraphicalData(); - } else { - getNodesAndDraw(); - } -} - -function getNodesAndDraw() { - var groupName = $.cookie('xcat_selectgrouponnodes'); - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'nodels', - tgt : groupName, - args : '', - msg : '' - }, - success : function(data) { - for (var temp in data.rsp) { - var nodeName = data.rsp[temp][0]; - if ('' == nodeName) { - continue; - } - fillList(nodeName); - } - $('#graphTab').empty(); - createGraphical(); - } - }); -} - -function fillList(nodeName, defaultnodetype) { - var parentName = ''; - var mtm = ''; - var status = ''; - var nodeType = ''; - var mpa = ''; - var unit = ''; - var rack = ''; - if (!graphicalNodeList[nodeName]) { - parentName = ''; - mtm = ''; - status = ''; - nodeType = defaultnodetype; - } else { - status = graphicalNodeList[nodeName]['status']; - nodeType = graphicalNodeList[nodeName]['type']; - switch (nodeType) { - case 'frame': - case 'lpar,osi': - case 'lpar': - case 'osi': - case 'cec': - parentName = graphicalNodeList[nodeName]['parent']; - mtm = graphicalNodeList[nodeName]['mtm']; - break; - case 'blade': - mpa = graphicalNodeList[nodeName]['mpa']; - unit = graphicalNodeList[nodeName]['unit']; - break; - case 'systemx': - rack = graphicalNodeList[nodeName]['rack']; - unit = graphicalNodeList[nodeName]['unit']; - break; - default: - break; - } - - } - - if ('' == status) { - status = 'unknown'; - } - - switch (nodeType) { - case 'frame': - if (undefined == bpaList[nodeName]) { - bpaList[nodeName] = new Array(); - } - - break; - case 'lpar,osi': - case 'lpar': - case 'osi': - if ('' == parentName) { - break; - } - - if (undefined == fspList[parentName]) { - fillList(parentName, 'cec'); - } - - fspList[parentName]['children'].push(nodeName); - lparList[nodeName] = status; - - break; - case 'cec': - if (undefined != fspList[nodeName]) { - break; - } - - fspList[nodeName] = new Object(); - fspList[nodeName]['children'] = new Array(); - fspList[nodeName]['mtm'] = mtm; - - if ('' == parentName) { - break; - } - - if (undefined == bpaList[parentName]) { - fillList(parentName, 'frame'); - } - - bpaList[parentName].push(nodeName); - break; - case 'blade': - if (undefined == bladeList[mpa]) { - bladeList[mpa] = new Array(); - } - bladeList[mpa].push(nodeName + ',' + unit); - - break; - case 'systemx': - if (!rack) { - rack = '_notsupply_'; - } - - if (undefined == rackList[rack]) { - rackList[rack] = new Array(); - } - - rackList[rack].push(nodeName + ',' + unit); - - break; - default: - unknownList.push(nodeName); - break; - } -} - -function createGraphical() { - var tabArea = $('#graphTab'); - var selectNodeDiv = $('
                  '); - var temp = 0; - for (var i in selectNode) { - temp++; - break; - } - - // There is no selected LPAR, show the info bar - if (temp == 0) { - tabArea.append(createInfoBar('Hover over a CEC and select the LPARs to do operations against.')); - } else { - // Show selected LPARs - updateSelectNodeDiv(); - } - - // Add buttons - tabArea.append(createActionMenu()); - tabArea.append(selectNodeDiv); - createSystempGraphical(bpaList, fspList, tabArea); - createBladeGraphical(bladeList, tabArea); - createSystemxGraphical(rackList, tabArea); - addUnknownGraphical(unknownList, tabArea); -} - -/** - * Create the physical/graphical layout for System p machines - * - * @param bpa All BPA and their related FSPs - * @param fsp All FSP and their related LPARs - * @param area The element to append graphical layout - */ -function createSystempGraphical(bpa, fsp, area) { - var usedFsp = new Object(); - var graphTable = $('
                  '); - var elementNum = 0; - var row = null; - var showFlag = false; - - // There is a node in the BPA list, so show add the title and show all frames - for (var bpaName in bpa) { - showFlag = true; - $('#graphTab').append('system p
                  '); - $('#graphTab').append(graphTable); - break; - } - - for (var bpaName in bpa) { - if (0 == elementNum % 3) { - row = $(''); - graphTable.append(row); - } - - elementNum++; - - var td = $(''); - var frameDiv = $('
                  '); - frameDiv.append('
                  '); - - // For P7-IH, all the CECs are insert into the frame from bottom to up, - // so we have to show the CECs same as the physical layout - var tempBlankDiv = $('
                  '); - var tempHeight = 0; - for (var fspIndex in bpa[bpaName]) { - var fspName = bpa[bpaName][fspIndex]; - usedFsp[fspName] = 1; - - // This is the P7-IH, we should add the blank at the top - if ((0 == fspIndex) && ('9125-F2C' == fsp[fspName]['mtm'])) { - frameDiv.append(tempBlankDiv); - } - - frameDiv.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp)); - frameDiv.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp)); - - tempHeight += calculateBlank(fsp[fspName]['mtm']); - } - - // tempHeight is the total height for all CECs, so we should minus BPA div - // height and CEC div heights - tempHeight = 428 - tempHeight; - tempBlankDiv.css('height', tempHeight); - td.append(frameDiv); - row.append(td); - } - - // Find the single FSP and sort descend by units - var singleFsp = new Array(); - for (var fspName in fsp) { - if (usedFsp[fspName]) { - continue; - } - - singleFsp.push([ fspName, fsp[fspName]['mtm'] ]); - } - - // If there is no frame, we should check if there is single CEC and show - // the title and add node area - if (!showFlag) { - for (var fspIndex in singleFsp) { - $('#graphTab').append('system p
                  '); - $('#graphTab').append(graphTable); - break; - } - } - - singleFsp.sort(function(a, b) { - var unitNumA = 4; - var unitNumB = 4; - if (hardwareInfo[a[1]]) { - unitNumA = hardwareInfo[a[1]][1]; - } - - if (hardwareInfo[b[1]]) { - unitNumB = hardwareInfo[b[1]][1]; - } - - return (unitNumB - unitNumA); - }); - - elementNum = 0; - for (var fspIndex in singleFsp) { - var fspName = singleFsp[fspIndex][0]; - if (0 == elementNum % 3) { - row = $(''); - graphTable.append(row); - } - elementNum++; - - var td = $(''); - td.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp)); - td.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp)); - row.append(td); - } - - $('.tooltip input[type = checkbox]').bind('click', function() { - var lparName = $(this).attr('name'); - if ('' == lparName) { - return; - } - if (true == $(this).attr('checked')) { - changeNode(lparName, 'select'); - } else { - changeNode(lparName, 'unselect'); - } - - updateSelectNodeDiv(); - }); - - $('.fspDiv2, .fspDiv4, .fspDiv42').tooltip({ - position : "center right", - relative : true, - offset : [ 10, -40 ], - effect : "fade", - opacity : 0.9 - }); - - $('.tooltip a').bind('click', function() { - var lparName = $(this).html(); - $('#nodesDatatable #' + lparName).trigger('click'); - }); - - $('.fspDiv2, .fspDiv4, .fspDiv42').bind('click', function() { - var fspName = $(this).attr('value'); - var selectCount = 0; - for (var lparIndex in fspList[fspName]['children']) { - var lparName = fspList[fspName]['children'][lparIndex]; - if (selectNode[lparName]) { - selectCount++; - } - } - - // All LPARs are selected, so unselect nodes - if (selectCount == fspList[fspName]['children'].length) { - for (var lparIndex in fspList[fspName]['children']) { - var lparName = fspList[fspName]['children'][lparIndex]; - changeNode(lparName, 'unselect'); - } - } - - // No selected LPARs on the cec, so add all LPARs into selectNode hash - else { - for (var lparIndex in fspList[fspName]['children']) { - var lparName = fspList[fspName]['children'][lparIndex]; - changeNode(lparName, 'select'); - } - } - - updateSelectNodeDiv(); - }); - - $('.fspCheckbox').bind('click', function() { - var itemName = $(this).attr('name'); - name = itemName.substr(6); - - if ($(this).attr('checked')) { - selectNode[name] = 1; - } else { - delete selectNode[name]; - } - - updateSelectNodeDiv(); - }); -} - -/** - * Create the physical/graphical layout for blades - * - * @param blades The blade list in global - * @param area The element to append the graphical layout - */ -function createBladeGraphical(blades, area) { - var graphTable = $('
                  '); - var mpa = ''; - var bladeName = ''; - var index = 0; - var mpaNumber = 0; - var row; - var showFlag = false; - - // Only show the title and nodes when there are blade in the blade list - for (mpa in blades) { - showFlag = true; - break; - } - - if (showFlag) { - $('#graphTab').append('Blade
                  '); - $('#graphTab').append(graphTable); - } - // If there is no blade node, return directly - else { - return; - } - - for (mpa in blades) { - var tempArray = new Array(14); - var bladeInfo = new Array(); - var unit = 0; - if (0 == mpaNumber % 3) { - row = $(''); - graphTable.append(row); - } - - mpaNumber++; - - var td = $(''); - var chasisDiv = $('
                  '); - - // Fill the array with blade information, to create the empty slot - for (index in blades[mpa]) { - bladeInfo = blades[mpa][index].split(','); - unit = parseInt(bladeInfo[1]); - tempArray[unit - 1] = bladeInfo[0]; - - } - - // Draw the blades and empty slot in chasis - for (index = 0; index < 14; index++) { - if (tempArray[index]) { - bladeName = tempArray[index]; - chasisDiv.append('
                  '); - } else { - chasisDiv.append('
                  '); - } - } - - td.append(chasisDiv); - row.append(td); - } - -} - -/** - * Create the physical/graphical layout for System x machines - * - * @param xnodes The system x node list in global - * @param area The element to append graphical layout - */ -function createSystemxGraphical(xnodes, area) { - var graphTable = $('
                  '); - var xnodename = ''; - var index = 0; - var rack = ''; - var row; - var xNodeCount = 0; - var showflag = false; - - // Only the title and System x node when there are x nodes in the list - for (rack in rackList) { - showflag = true; - break; - } - - if (showflag) { - $('#graphTab').append('system x
                  '); - $('#graphTab').append(graphTable); - } - // There is nothing to show, return directly - else { - return; - } - - for (rack in rackList) { - for (index in rackList[rack]) { - var xNodeName = rackList[rack][index]; - if (0 == xNodeCount % 3) { - row = $(''); - graphTable.append(row); - } - xNodeCount++; - var td = $(''); - var xNodeDiv = '
                  '; - td.append(xNodeDiv); - row.append(td); - } - } -} - -function addUnknownGraphical(unknownNodes, tab) { - // Do not continue if no nodes were found - if (unknownNodes.length < 1) - return; - - var list = ""; - tab.append('
                  '); - for (var index in unknownNodes) { - list += unknownNodes[index] + ', '; - - } - - // Delete last comma - list = list.substr(0, list.length - 2); - tab.append(list); -} - -/** - * Update the LPARs background in CEC, LPAR area and selectNode - */ -function updateSelectNodeDiv() { - var temp = 0; - $('#selectNodeDiv').empty(); - - // Add buttons - if (selectNode.length) { - $('#selectNodeDiv').append('Nodes: '); - for (var lparName in selectNode) { - $('#selectNodeDiv').append(lparName + ' '); - temp++; - if (temp > 6) { - $('#selectNodeDiv').append('...'); - break; - } - } - } -} - -/** - * Create the action menu - */ -function createActionMenu() { - // Create action bar - var actionBar = $('
                  ').css("width", "400px"); - - // Power on - var powerOnLnk = $('Power on'); - powerOnLnk.click(function() { - var tgtNodes = getSelectNodes(); - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'rpower', - tgt : tgtNodes, - args : 'on', - msg : '' - } - }); - }); - - // Power off - var powerOffLnk = $('Power off'); - powerOffLnk.click(function() { - var tgtNodes = getSelectNodes(); - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'rpower', - tgt : tgtNodes, - args : 'off', - msg : '' - } - }); - }); - - // Delete - var deleteLnk = $('Delete'); - deleteLnk.click(function() { - var tgtNodes = getSelectNodes(); - if (tgtNodes) { - loadDeletePage(tgtNodes); - } - }); - - // Unlock - var unlockLnk = $('Unlock'); - unlockLnk.click(function() { - var tgtNodes = getSelectNodes(); - if (tgtNodes) { - loadUnlockPage(tgtNodes); - } - }); - - // Run script - var scriptLnk = $('Run script'); - scriptLnk.click(function() { - var tgtNodes = getSelectNodes(); - if (tgtNodes) { - loadScriptPage(tgtNodes); - } - }); - - // Update - var updateLnk = $('Update'); - updateLnk.click(function() { - var tgtNodes = getSelectNodes(); - if (tgtNodes) { - loadUpdatenodePage(tgtNodes); - } - }); - - // Set boot state - var setBootStateLnk = $('Set boot state'); - setBootStateLnk.click(function() { - var tgtNodes = getSelectNodes(); - if (tgtNodes) { - loadNodesetPage(tgtNodes); - } - }); - - // Boot to network - var boot2NetworkLnk = $('Boot to network'); - boot2NetworkLnk.click(function() { - var tgtNodes = getSelectNodes(); - if (tgtNodes) { - loadNetbootPage(tgtNodes); - } - }); - - // Remote console - var rconLnk = $('Open console'); - rconLnk.bind('click', function(event) { - var tgtNodes = getSelectNodes(); - if (tgtNodes) { - loadRconsPage(tgtNodes); - } - }); - - // Edit properties - var editProps = $('Edit properties'); - editProps.bind('click', function(event) { - for (var node in selectNode) { - loadEditPropsPage(node); - } - }); - - // Actions - var actionsLnk = 'Actions'; - var actsMenu = createMenu([ deleteLnk, powerOnLnk, powerOffLnk, scriptLnk ]); - - // Configurations - var configLnk = 'Configuration'; - var configMenu = createMenu([ unlockLnk, updateLnk, editProps ]); - - // Provision - var provLnk = 'Provision'; - var provMenu = createMenu([ boot2NetworkLnk, setBootStateLnk, rconLnk ]); - - // Create an action menu - var actionsMenu = createMenu([ [ actionsLnk, actsMenu ], - [ configLnk, configMenu ], [ provLnk, provMenu ] ]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - actionBar.css('margin-top', '10px'); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - return actionBar; -} - -/** - * Create the physical/graphical layout - */ -function createFspDiv(fspName, mtm, fsp) { - // Create FSP title - var lparStatusRow = ''; - var temp = ''; - - for (var lparIndex in fsp[fspName]['children']) { - // Show 8 lpars on one cec at most. - if (lparIndex >= 8) { - break; - } - - var lparName = fsp[fspName]['children'][lparIndex]; - var color = statusMap(lparList[lparName]); - lparStatusRow += ''; - } - - // Select the backgroud - var divClass = ''; - if ('' == mtm) { - temp = '8231-E2B'; - } else { - temp = mtm; - } - - if (!hardwareInfo[temp]){ - hardwareInfo[temp] = ['unkown', 2]; - } - - if (hardwareInfo[temp][1]) { - divClass += 'fspDiv' + hardwareInfo[temp][1]; - } else { - divClass += 'fspDiv4'; - } - - // Create return value - var retHtml = ''; - retHtml += '
                  '; - retHtml += '
                  ' + lparStatusRow - + '
                  '; - return retHtml; -} - -/** - * Create the physical/graphical FSP tooltip which is used to select the LPAR - */ -function createFspTip(fspName, mtm, fsp) { - var tip = $('
                  '); - var tempTable = $('
                  '); - var temp = ''; - if ('' == mtm) { - temp = 'unkown'; - } else { - temp = mtm; - } - - if (hardwareInfo[temp]) { - tip.append('

                  ' + fspName + '(' + hardwareInfo[temp][0] + ')


                  '); - } else { - tip.append('

                  ' + fspName + '


                  '); - } - - for (var lparIndex in fsp[fspName]['children']) { - var lparName = fsp[fspName]['children'][lparIndex]; - var color = statusMap(lparList[lparName]); - var row = ''; - row += '' + lparName + ''; - row += '' + lparList[lparName] + ''; - tempTable.append(row); - } - - tip.append(tempTable); - return tip; -} -/** - * Map the LPAR status into a color - * - * @param status LPAR status in nodelist table - * @return Corresponding color name - */ -function statusMap(status) { - var color = 'gainsboro'; - - switch (status) { - case 'alive': - case 'ready': - case 'pbs': - case 'sshd': - case 'booting': - case 'booted': - case 'ping': - color = 'green'; - break; - case 'noping': - case 'unreachable': - color = 'red'; - break; - default: - color = 'grey'; - break; - } - - return color; -} - -/** - * Select all LPAR checkboxes - */ -function selectAllLpars(checkbox) { - var temp = checkbox.attr('checked'); - $('#selectNodeTable input[type = checkbox]').attr('checked', temp); -} - -/** - * Export all LPAR names from selectNode - * - * @return lpars' string - */ -function getSelectNodes() { - var ret = ''; - for (var lparName in selectNode) { - ret += lparName + ','; - } - - return ret.substring(0, ret.length - 1); -} - -/** - * When the node is selected or unselected, update the area on CEC, update - * the global list, and update the tooltip table - */ -function changeNode(lparName, status) { - var imgUrl = ''; - var checkFlag = true; - if ('select' == status) { - selectNode[lparName] = 1; - imgUrl = 'url(images/nodes/s-' + statusMap(lparList[lparName]) - + '.gif)'; - checkFlag = true; - } else { - delete selectNode[lparName]; - imgUrl = 'url(images/nodes/' + statusMap(lparList[lparName]) + '.gif)'; - checkFlag = false; - } - $('#' + lparName + 'status').css('background-image', imgUrl); - $('.tooltip input[name="' + lparName + '"]').attr('checked', checkFlag); -} - -/** - * The P7-IH's CECs are insert from bottom to up, so we had to calculate the blank height - * - * @return Height for the CEC - */ -function calculateBlank(mtm) { - if ('' == mtm) { - return 24; - } - - if (!hardwareInfo[mtm]) { - return 24; - } - - switch (hardwareInfo[mtm][1]) { - case 1: - return 13; - break; - case 2: - return 24; - break; - case 4: - return 47; - break; - default: - return 0; - break; - } +var bpaList; +var fspList; +var lparList; +var bladeList; +var rackList; +var unknownList; +var graphicalNodeList; +var selectNode; + +/** + * Get all nodes useful attributes from remote server + * + * @param dataTypeIndex The index in the array which contains attributes we need. + * @param attrNullNode The target node list for this attribute + */ +function initGraphicalData() { + $('#graphTab').append(createLoader()); + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'graph', + msg : '' + }, + success : function(data) { + data = decodeRsp(data); + if (!data.rsp[0]) { + return; + } + extractGraphicalData(data.rsp[0]); + getNodesAndDraw(); + } + }); +} + +/** + * Extract all nodes userful data into a hash, which will be used for creating graphical + * + * @param data The response from xCAT command 'nodels all nodetype.nodetype ppc.parent ...' + * @return nodes list for next time query + */ +function extractGraphicalData(data) { + var nodes = data.split(';'); + var attrs; + var nodeName; + + // Extract useful info into tempList + for (var i = 0; i < nodes.length; i++) { + attrs = nodes[i].split(':'); + nodeName = attrs[0]; + if (undefined == graphicalNodeList[nodeName]) { + graphicalNodeList[nodeName] = new Object(); + } + + graphicalNodeList[nodeName]['type'] = attrs[1].toLowerCase(); + switch (attrs[1].toLowerCase()) { + case 'cec': + case 'frame': + case 'lpar': + case 'lpar,osi': + case 'osi,lpar': + graphicalNodeList[nodeName]['parent'] = attrs[2]; + graphicalNodeList[nodeName]['mtm'] = attrs[3]; + graphicalNodeList[nodeName]['status'] = attrs[4]; + break; + case 'blade': + graphicalNodeList[nodeName]['mpa'] = attrs[2]; + graphicalNodeList[nodeName]['unit'] = attrs[3]; + graphicalNodeList[nodeName]['status'] = attrs[4]; + break; + case 'systemx': + graphicalNodeList[nodeName]['rack'] = attrs[2]; + graphicalNodeList[nodeName]['unit'] = attrs[3]; + graphicalNodeList[nodeName]['mtm'] = attrs[4]; + graphicalNodeList[nodeName]['status'] = attrs[5]; + break; + default: + break; + } + } +} + +function createPhysicalLayout(nodeList) { + var flag = false; + + // When the graphical layout is shown, do not need to redraw + if (1 < $('#graphTab').children().length) { + return; + } + + // Save the new selected nodes + if (graphicalNodeList) { + for (var i in graphicalNodeList) { + flag = true; + break; + } + } + + bpaList = new Object(); + fspList = new Object(); + lparList = new Object(); + bladeList = new Object(); + selectNode = new Object(); + rackList = new Object(); + unknownList = new Array(); + + // There is no graphical data, get the info now + if (!flag) { + graphicalNodeList = new Object(); + initGraphicalData(); + } else { + getNodesAndDraw(); + } +} + +function getNodesAndDraw() { + var groupName = $.cookie('xcat_selectgrouponnodes'); + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'nodels', + tgt : groupName, + args : '', + msg : '' + }, + success : function(data) { + data = decodeRsp(data); + for (var temp in data.rsp) { + var nodeName = data.rsp[temp][0]; + if ('' == nodeName) { + continue; + } + fillList(nodeName); + } + $('#graphTab').empty(); + createGraphical(); + } + }); +} + +function fillList(nodeName, defaultnodetype) { + var parentName = ''; + var mtm = ''; + var status = ''; + var nodeType = ''; + var mpa = ''; + var unit = ''; + var rack = ''; + if (!graphicalNodeList[nodeName]) { + parentName = ''; + mtm = ''; + status = ''; + nodeType = defaultnodetype; + } else { + status = graphicalNodeList[nodeName]['status']; + nodeType = graphicalNodeList[nodeName]['type']; + switch (nodeType) { + case 'frame': + case 'lpar,osi': + case 'lpar': + case 'osi': + case 'cec': + parentName = graphicalNodeList[nodeName]['parent']; + mtm = graphicalNodeList[nodeName]['mtm']; + break; + case 'blade': + mpa = graphicalNodeList[nodeName]['mpa']; + unit = graphicalNodeList[nodeName]['unit']; + break; + case 'systemx': + rack = graphicalNodeList[nodeName]['rack']; + unit = graphicalNodeList[nodeName]['unit']; + break; + default: + break; + } + + } + + if ('' == status) { + status = 'unknown'; + } + + switch (nodeType) { + case 'frame': + if (undefined == bpaList[nodeName]) { + bpaList[nodeName] = new Array(); + } + + break; + case 'lpar,osi': + case 'lpar': + case 'osi': + if ('' == parentName) { + break; + } + + if (undefined == fspList[parentName]) { + fillList(parentName, 'cec'); + } + + fspList[parentName]['children'].push(nodeName); + lparList[nodeName] = status; + + break; + case 'cec': + if (undefined != fspList[nodeName]) { + break; + } + + fspList[nodeName] = new Object(); + fspList[nodeName]['children'] = new Array(); + fspList[nodeName]['mtm'] = mtm; + + if ('' == parentName) { + break; + } + + if (undefined == bpaList[parentName]) { + fillList(parentName, 'frame'); + } + + bpaList[parentName].push(nodeName); + break; + case 'blade': + if (undefined == bladeList[mpa]) { + bladeList[mpa] = new Array(); + } + bladeList[mpa].push(nodeName + ',' + unit); + + break; + case 'systemx': + if (!rack) { + rack = '_notsupply_'; + } + + if (undefined == rackList[rack]) { + rackList[rack] = new Array(); + } + + rackList[rack].push(nodeName + ',' + unit); + + break; + default: + unknownList.push(nodeName); + break; + } +} + +function createGraphical() { + var tabArea = $('#graphTab'); + var selectNodeDiv = $('
                  '); + var temp = 0; + for (var i in selectNode) { + temp++; + break; + } + + // There is no selected LPAR, show the info bar + if (temp == 0) { + tabArea.append(createInfoBar('Hover over a CEC and select the LPARs to do operations against.')); + } else { + // Show selected LPARs + updateSelectNodeDiv(); + } + + // Add buttons + tabArea.append(createActionMenu()); + tabArea.append(selectNodeDiv); + createSystempGraphical(bpaList, fspList, tabArea); + createBladeGraphical(bladeList, tabArea); + createSystemxGraphical(rackList, tabArea); + addUnknownGraphical(unknownList, tabArea); +} + +/** + * Create the physical/graphical layout for System p machines + * + * @param bpa All BPA and their related FSPs + * @param fsp All FSP and their related LPARs + * @param area The element to append graphical layout + */ +function createSystempGraphical(bpa, fsp, area) { + var usedFsp = new Object(); + var graphTable = $('
                  '); + var elementNum = 0; + var row = null; + var showFlag = false; + + // There is a node in the BPA list, so show add the title and show all frames + for (var bpaName in bpa) { + showFlag = true; + $('#graphTab').append('system p
                  '); + $('#graphTab').append(graphTable); + break; + } + + for (var bpaName in bpa) { + if (0 == elementNum % 3) { + row = $(''); + graphTable.append(row); + } + + elementNum++; + + var td = $(''); + var frameDiv = $('
                  '); + frameDiv.append('
                  '); + + // For P7-IH, all the CECs are insert into the frame from bottom to up, + // so we have to show the CECs same as the physical layout + var tempBlankDiv = $('
                  '); + var tempHeight = 0; + for (var fspIndex in bpa[bpaName]) { + var fspName = bpa[bpaName][fspIndex]; + usedFsp[fspName] = 1; + + // This is the P7-IH, we should add the blank at the top + if ((0 == fspIndex) && ('9125-F2C' == fsp[fspName]['mtm'])) { + frameDiv.append(tempBlankDiv); + } + + frameDiv.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp)); + frameDiv.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp)); + + tempHeight += calculateBlank(fsp[fspName]['mtm']); + } + + // tempHeight is the total height for all CECs, so we should minus BPA div + // height and CEC div heights + tempHeight = 428 - tempHeight; + tempBlankDiv.css('height', tempHeight); + td.append(frameDiv); + row.append(td); + } + + // Find the single FSP and sort descend by units + var singleFsp = new Array(); + for (var fspName in fsp) { + if (usedFsp[fspName]) { + continue; + } + + singleFsp.push([ fspName, fsp[fspName]['mtm'] ]); + } + + // If there is no frame, we should check if there is single CEC and show + // the title and add node area + if (!showFlag) { + for (var fspIndex in singleFsp) { + $('#graphTab').append('system p
                  '); + $('#graphTab').append(graphTable); + break; + } + } + + singleFsp.sort(function(a, b) { + var unitNumA = 4; + var unitNumB = 4; + if (hardwareInfo[a[1]]) { + unitNumA = hardwareInfo[a[1]][1]; + } + + if (hardwareInfo[b[1]]) { + unitNumB = hardwareInfo[b[1]][1]; + } + + return (unitNumB - unitNumA); + }); + + elementNum = 0; + for (var fspIndex in singleFsp) { + var fspName = singleFsp[fspIndex][0]; + if (0 == elementNum % 3) { + row = $(''); + graphTable.append(row); + } + elementNum++; + + var td = $(''); + td.append(createFspDiv(fspName, fsp[fspName]['mtm'], fsp)); + td.append(createFspTip(fspName, fsp[fspName]['mtm'], fsp)); + row.append(td); + } + + $('.tooltip input[type = checkbox]').bind('click', function() { + var lparName = $(this).attr('name'); + if ('' == lparName) { + return; + } + if (true == $(this).attr('checked')) { + changeNode(lparName, 'select'); + } else { + changeNode(lparName, 'unselect'); + } + + updateSelectNodeDiv(); + }); + + $('.fspDiv2, .fspDiv4, .fspDiv42').tooltip({ + position : "center right", + relative : true, + offset : [ 10, -40 ], + effect : "fade", + opacity : 0.9 + }); + + $('.tooltip a').bind('click', function() { + var lparName = $(this).html(); + $('#nodesDatatable #' + lparName).trigger('click'); + }); + + $('.fspDiv2, .fspDiv4, .fspDiv42').bind('click', function() { + var fspName = $(this).attr('value'); + var selectCount = 0; + for (var lparIndex in fspList[fspName]['children']) { + var lparName = fspList[fspName]['children'][lparIndex]; + if (selectNode[lparName]) { + selectCount++; + } + } + + // All LPARs are selected, so unselect nodes + if (selectCount == fspList[fspName]['children'].length) { + for (var lparIndex in fspList[fspName]['children']) { + var lparName = fspList[fspName]['children'][lparIndex]; + changeNode(lparName, 'unselect'); + } + } + + // No selected LPARs on the cec, so add all LPARs into selectNode hash + else { + for (var lparIndex in fspList[fspName]['children']) { + var lparName = fspList[fspName]['children'][lparIndex]; + changeNode(lparName, 'select'); + } + } + + updateSelectNodeDiv(); + }); + + $('.fspCheckbox').bind('click', function() { + var itemName = $(this).attr('name'); + name = itemName.substr(6); + + if ($(this).attr('checked')) { + selectNode[name] = 1; + } else { + delete selectNode[name]; + } + + updateSelectNodeDiv(); + }); +} + +/** + * Create the physical/graphical layout for blades + * + * @param blades The blade list in global + * @param area The element to append the graphical layout + */ +function createBladeGraphical(blades, area) { + var graphTable = $('
                  '); + var mpa = ''; + var bladeName = ''; + var index = 0; + var mpaNumber = 0; + var row; + var showFlag = false; + + // Only show the title and nodes when there are blade in the blade list + for (mpa in blades) { + showFlag = true; + break; + } + + if (showFlag) { + $('#graphTab').append('Blade
                  '); + $('#graphTab').append(graphTable); + } + // If there is no blade node, return directly + else { + return; + } + + for (mpa in blades) { + var tempArray = new Array(14); + var bladeInfo = new Array(); + var unit = 0; + if (0 == mpaNumber % 3) { + row = $(''); + graphTable.append(row); + } + + mpaNumber++; + + var td = $(''); + var chasisDiv = $('
                  '); + + // Fill the array with blade information, to create the empty slot + for (index in blades[mpa]) { + bladeInfo = blades[mpa][index].split(','); + unit = parseInt(bladeInfo[1]); + tempArray[unit - 1] = bladeInfo[0]; + + } + + // Draw the blades and empty slot in chasis + for (index = 0; index < 14; index++) { + if (tempArray[index]) { + bladeName = tempArray[index]; + chasisDiv.append('
                  '); + } else { + chasisDiv.append('
                  '); + } + } + + td.append(chasisDiv); + row.append(td); + } + +} + +/** + * Create the physical/graphical layout for System x machines + * + * @param xnodes The system x node list in global + * @param area The element to append graphical layout + */ +function createSystemxGraphical(xnodes, area) { + var graphTable = $('
                  '); + var xnodename = ''; + var index = 0; + var rack = ''; + var row; + var xNodeCount = 0; + var showflag = false; + + // Only the title and System x node when there are x nodes in the list + for (rack in rackList) { + showflag = true; + break; + } + + if (showflag) { + $('#graphTab').append('system x
                  '); + $('#graphTab').append(graphTable); + } + // There is nothing to show, return directly + else { + return; + } + + for (rack in rackList) { + for (index in rackList[rack]) { + var xNodeName = rackList[rack][index]; + if (0 == xNodeCount % 3) { + row = $(''); + graphTable.append(row); + } + xNodeCount++; + var td = $(''); + var xNodeDiv = '
                  '; + td.append(xNodeDiv); + row.append(td); + } + } +} + +function addUnknownGraphical(unknownNodes, tab) { + // Do not continue if no nodes were found + if (unknownNodes.length < 1) + return; + + var list = ""; + tab.append('
                  '); + for (var index in unknownNodes) { + list += unknownNodes[index] + ', '; + + } + + // Delete last comma + list = list.substr(0, list.length - 2); + tab.append(list); +} + +/** + * Update the LPARs background in CEC, LPAR area and selectNode + */ +function updateSelectNodeDiv() { + var temp = 0; + $('#selectNodeDiv').empty(); + + // Add buttons + if (selectNode.length) { + $('#selectNodeDiv').append('Nodes: '); + for (var lparName in selectNode) { + $('#selectNodeDiv').append(lparName + ' '); + temp++; + if (temp > 6) { + $('#selectNodeDiv').append('...'); + break; + } + } + } +} + +/** + * Create the action menu + */ +function createActionMenu() { + // Create action bar + var actionBar = $('
                  ').css("width", "400px"); + + // Power on + var powerOnLnk = $('Power on'); + powerOnLnk.click(function() { + var tgtNodes = getSelectNodes(); + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rpower', + tgt : tgtNodes, + args : 'on', + msg : '' + } + }); + }); + + // Power off + var powerOffLnk = $('Power off'); + powerOffLnk.click(function() { + var tgtNodes = getSelectNodes(); + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rpower', + tgt : tgtNodes, + args : 'off', + msg : '' + } + }); + }); + + // Delete + var deleteLnk = $('Delete'); + deleteLnk.click(function() { + var tgtNodes = getSelectNodes(); + if (tgtNodes) { + loadDeletePage(tgtNodes); + } + }); + + // Unlock + var unlockLnk = $('Unlock'); + unlockLnk.click(function() { + var tgtNodes = getSelectNodes(); + if (tgtNodes) { + loadUnlockPage(tgtNodes); + } + }); + + // Run script + var scriptLnk = $('Run script'); + scriptLnk.click(function() { + var tgtNodes = getSelectNodes(); + if (tgtNodes) { + loadScriptPage(tgtNodes); + } + }); + + // Update + var updateLnk = $('Update'); + updateLnk.click(function() { + var tgtNodes = getSelectNodes(); + if (tgtNodes) { + loadUpdatenodePage(tgtNodes); + } + }); + + // Set boot state + var setBootStateLnk = $('Set boot state'); + setBootStateLnk.click(function() { + var tgtNodes = getSelectNodes(); + if (tgtNodes) { + loadNodesetPage(tgtNodes); + } + }); + + // Boot to network + var boot2NetworkLnk = $('Boot to network'); + boot2NetworkLnk.click(function() { + var tgtNodes = getSelectNodes(); + if (tgtNodes) { + loadNetbootPage(tgtNodes); + } + }); + + // Remote console + var rconLnk = $('Open console'); + rconLnk.bind('click', function(event) { + var tgtNodes = getSelectNodes(); + if (tgtNodes) { + loadRconsPage(tgtNodes); + } + }); + + // Edit properties + var editProps = $('Edit properties'); + editProps.bind('click', function(event) { + for (var node in selectNode) { + loadEditPropsPage(node); + } + }); + + // Actions + var actionsLnk = 'Actions'; + var actsMenu = createMenu([ deleteLnk, powerOnLnk, powerOffLnk, scriptLnk ]); + + // Configurations + var configLnk = 'Configuration'; + var configMenu = createMenu([ unlockLnk, updateLnk, editProps ]); + + // Provision + var provLnk = 'Provision'; + var provMenu = createMenu([ boot2NetworkLnk, setBootStateLnk, rconLnk ]); + + // Create an action menu + var actionsMenu = createMenu([ [ actionsLnk, actsMenu ], + [ configLnk, configMenu ], [ provLnk, provMenu ] ]); + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + actionBar.css('margin-top', '10px'); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + return actionBar; +} + +/** + * Create the physical/graphical layout + */ +function createFspDiv(fspName, mtm, fsp) { + // Create FSP title + var lparStatusRow = ''; + var temp = ''; + + for (var lparIndex in fsp[fspName]['children']) { + // Show 8 lpars on one cec at most. + if (lparIndex >= 8) { + break; + } + + var lparName = fsp[fspName]['children'][lparIndex]; + var color = statusMap(lparList[lparName]); + lparStatusRow += ''; + } + + // Select the backgroud + var divClass = ''; + if ('' == mtm) { + temp = '8231-E2B'; + } else { + temp = mtm; + } + + if (!hardwareInfo[temp]){ + hardwareInfo[temp] = ['unkown', 2]; + } + + if (hardwareInfo[temp][1]) { + divClass += 'fspDiv' + hardwareInfo[temp][1]; + } else { + divClass += 'fspDiv4'; + } + + // Create return value + var retHtml = ''; + retHtml += '
                  '; + retHtml += '
                  ' + lparStatusRow + + '
                  '; + return retHtml; +} + +/** + * Create the physical/graphical FSP tooltip which is used to select the LPAR + */ +function createFspTip(fspName, mtm, fsp) { + var tip = $('
                  '); + var tempTable = $('
                  '); + var temp = ''; + if ('' == mtm) { + temp = 'unkown'; + } else { + temp = mtm; + } + + if (hardwareInfo[temp]) { + tip.append('

                  ' + fspName + '(' + hardwareInfo[temp][0] + ')


                  '); + } else { + tip.append('

                  ' + fspName + '


                  '); + } + + for (var lparIndex in fsp[fspName]['children']) { + var lparName = fsp[fspName]['children'][lparIndex]; + var color = statusMap(lparList[lparName]); + var row = ''; + row += '' + lparName + ''; + row += '' + lparList[lparName] + ''; + tempTable.append(row); + } + + tip.append(tempTable); + return tip; +} +/** + * Map the LPAR status into a color + * + * @param status LPAR status in nodelist table + * @return Corresponding color name + */ +function statusMap(status) { + var color = 'gainsboro'; + + switch (status) { + case 'alive': + case 'ready': + case 'pbs': + case 'sshd': + case 'booting': + case 'booted': + case 'ping': + color = 'green'; + break; + case 'noping': + case 'unreachable': + color = 'red'; + break; + default: + color = 'grey'; + break; + } + + return color; +} + +/** + * Select all LPAR checkboxes + */ +function selectAllLpars(checkbox) { + var temp = checkbox.attr('checked'); + $('#selectNodeTable input[type = checkbox]').attr('checked', temp); +} + +/** + * Export all LPAR names from selectNode + * + * @return lpars' string + */ +function getSelectNodes() { + var ret = ''; + for (var lparName in selectNode) { + ret += lparName + ','; + } + + return ret.substring(0, ret.length - 1); +} + +/** + * When the node is selected or unselected, update the area on CEC, update + * the global list, and update the tooltip table + */ +function changeNode(lparName, status) { + var imgUrl = ''; + var checkFlag = true; + if ('select' == status) { + selectNode[lparName] = 1; + imgUrl = 'url(images/nodes/s-' + statusMap(lparList[lparName]) + + '.gif)'; + checkFlag = true; + } else { + delete selectNode[lparName]; + imgUrl = 'url(images/nodes/' + statusMap(lparList[lparName]) + '.gif)'; + checkFlag = false; + } + $('#' + lparName + 'status').css('background-image', imgUrl); + $('.tooltip input[name="' + lparName + '"]').attr('checked', checkFlag); +} + +/** + * The P7-IH's CECs are insert from bottom to up, so we had to calculate the blank height + * + * @return Height for the CEC + */ +function calculateBlank(mtm) { + if ('' == mtm) { + return 24; + } + + if (!hardwareInfo[mtm]) { + return 24; + } + + switch (hardwareInfo[mtm][1]) { + case 1: + return 13; + break; + case 2: + return 24; + break; + case 4: + return 47; + break; + default: + return 0; + break; + } } \ No newline at end of file diff --git a/xCAT-UI/js/nodes/rnetboot.js b/xCAT-UI/js/nodes/rnetboot.js index c745c8922..7f03e069b 100644 --- a/xCAT-UI/js/nodes/rnetboot.js +++ b/xCAT-UI/js/nodes/rnetboot.js @@ -1,220 +1,223 @@ -/** - * Load netboot page - * - * @param tgtNodes Targets to run rnetboot against - */ -function loadNetbootPage(tgtNodes) { - // Get node OS - var osHash = new Object(); - var nodes = tgtNodes.split(','); - for (var i in nodes) { - var os = getNodeAttr(nodes[i], 'os'); - var osBase = os.match(/[a-zA-Z]+/); - if (osBase) { - nodes[osBase] = 1; - } - } - - // Get nodes tab - var tab = getNodesTab(); - - // Generate new tab ID - var inst = 0; - var newTabId = 'netbootTab' + inst; - while ($('#' + newTabId).length) { - // If one already exists, generate another one - inst = inst + 1; - newTabId = 'netbootTab' + inst; - } - - // Create netboot form - var netbootForm = $('
                  '); - - // Create status bar - var statBarId = 'netbootStatusBar' + inst; - var statusBar = createStatusBar(statBarId).hide(); - - // Create loader - var loader = createLoader('netbootLoader'); - statusBar.find('div').append(loader); - - // Create info bar - var infoBar = createInfoBar('Cause the range of nodes to boot to network'); - netbootForm.append(statusBar, infoBar); - - // Create VM fieldset - var vmFS = $('
                  '); - var vmLegend = $('Virtual Machine'); - vmFS.append(vmLegend); - netbootForm.append(vmFS); - - var vmAttr = $('
                  '); - vmFS.append($('
                  ')); - vmFS.append(vmAttr); - - // Create options fieldset - var optionsFS = $('
                  '); - var optionsLegend = $('Options'); - optionsFS.append(optionsLegend); - netbootForm.append(optionsFS); - - var optionsAttr = $('
                  '); - optionsFS.append($('
                  ')); - optionsFS.append(optionsAttr); - - // Create target node or group input - var target = $('
                  '); - vmAttr.append(target); - - // Create options - var optsLabel = $(''); - var optsList = $('
                    '); - optionsAttr.append(optsList); - - // Create boot order checkbox - var opt = $('
                  • '); - var bootOrderChkBox = $(''); - opt.append(bootOrderChkBox); - opt.append('Set the boot device order'); - optsList.append(opt); - // Create boot order input - var bootOrder = $('
                  • '); - bootOrder.hide(); - optsList.append(bootOrder); - - // Create force reboot checkbox - optsList.append('
                  • Force reboot
                  • '); - // Create force shutdown checkbox - optsList.append('
                  • Force immediate shutdown of the partition
                  • '); - if (osHash['AIX']) { - // Create iscsi dump checkbox - optsList.append('
                  • Do a iscsi dump on AIX
                  • '); - } - - // Show boot order when checkbox is checked - bootOrderChkBox.bind('click', function(event) { - if ($(this).is(':checked')) { - bootOrder.show(); - } else { - bootOrder.hide(); - } - }); - - // Determine plugin - var tmp = tgtNodes.split(','); - for ( var i = 0; i < tmp.length; i++) { - var mgt = getNodeAttr(tmp[i], 'mgt'); - // If it is zvm - if (mgt == 'zvm') { - // Add IPL input - optsList.append('
                    '); - break; - } - } - - // Generate tooltips - netbootForm.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" - } - }); - - /** - * Ok - */ - var okBtn = createButton('Ok'); - okBtn.css({ - 'width': '80px', - 'display': 'block' - }); - okBtn.bind('click', function(event) { - // Remove any warning messages - $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); - - // Check inputs - var ready = true; - var inputs = $("#" + newTabId + " input[type='text']:visible"); - for ( var i = 0; i < inputs.length; i++) { - if (!inputs.eq(i).val()) { - inputs.eq(i).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - inputs.eq(i).css('border', 'solid #BDBDBD 1px'); - } - } - - // Generate arguments - var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); - var optStr = ''; - var opt; - for ( var i = 0; i < chkBoxes.length; i++) { - opt = chkBoxes.eq(i).attr('name'); - optStr += '-' + opt; - - // If it is the boot order - if (opt == 's') { - // Get the boot order - optStr += ';' + $('#' + newTabId + ' input[name=bootOrder]').val(); - } - - // Append ; to end of string - if (i < (chkBoxes.length - 1)) { - optStr += ';'; - } - } - - // If no inputs are empty - if (ready) { - // Get nodes - var tgts = $('#' + newTabId + ' input[name=target]').val(); - - // Get IPL address - var ipl = $('#' + newTabId + ' input[name=ipl]'); - if (ipl) { - optStr += 'ipl=' + ipl.val(); - } - - // Disable all inputs and Ok button - $('#' + newTabId + ' input').attr('disabled', 'disabled'); - $(this).attr('disabled', 'true'); - - /** - * (1) Boot to network - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'rnetboot', - tgt : tgts, - args : optStr, - msg : 'out=' + statBarId + ';cmd=rnetboot;tgt=' + tgts - }, - - success : updateStatusBar - }); - - // Show status bar - statusBar.show(); - } else { - // Show warning message - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this).parents('.ui-tabs-panel')); - } - }); - netbootForm.append(okBtn); - - // Append to discover tab - tab.add(newTabId, 'Boot', netbootForm, true); - - // Select new tab - tab.select(newTabId); +/** + * Load netboot page + * + * @param tgtNodes Targets to run rnetboot against + */ +function loadNetbootPage(tgtNodes) { + // Get node OS + var osHash = new Object(); + var nodes = tgtNodes.split(','); + for (var i in nodes) { + var os = getNodeAttr(nodes[i], 'os'); + var osBase = os.match(/[a-zA-Z]+/); + if (osBase) { + nodes[osBase] = 1; + } + } + + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'netbootTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'netbootTab' + inst; + } + + // Create netboot form + var netbootForm = $('
                    '); + + // Create status bar + var statBarId = 'netbootStatusBar' + inst; + var statusBar = createStatusBar(statBarId).hide(); + + // Create loader + var loader = createLoader('netbootLoader'); + statusBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('Cause the range of nodes to boot to network'); + netbootForm.append(statusBar, infoBar); + + // Create VM fieldset + var vmFS = $('
                    '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + netbootForm.append(vmFS); + + var vmAttr = $('
                    '); + vmFS.append($('
                    ')); + vmFS.append(vmAttr); + + // Create options fieldset + var optionsFS = $('
                    '); + var optionsLegend = $('Options'); + optionsFS.append(optionsLegend); + netbootForm.append(optionsFS); + + var optionsAttr = $('
                    '); + optionsFS.append($('
                    ')); + optionsFS.append(optionsAttr); + + // Create target node or group input + var target = $('
                    '); + vmAttr.append(target); + + // Create options + var optsLabel = $(''); + var optsList = $('
                      '); + optionsAttr.append(optsList); + + // Create boot order checkbox + var opt = $('
                    • '); + var bootOrderChkBox = $(''); + opt.append(bootOrderChkBox); + opt.append('Set the boot device order'); + optsList.append(opt); + // Create boot order input + var bootOrder = $('
                    • '); + bootOrder.hide(); + optsList.append(bootOrder); + + // Create force reboot checkbox + optsList.append('
                    • Force reboot
                    • '); + // Create force shutdown checkbox + optsList.append('
                    • Force immediate shutdown of the partition
                    • '); + if (osHash['AIX']) { + // Create iscsi dump checkbox + optsList.append('
                    • Do a iscsi dump on AIX
                    • '); + } + + // Show boot order when checkbox is checked + bootOrderChkBox.bind('click', function(event) { + if ($(this).is(':checked')) { + bootOrder.show(); + } else { + bootOrder.hide(); + } + }); + + // Determine plugin + var tmp = tgtNodes.split(','); + for ( var i = 0; i < tmp.length; i++) { + var mgt = getNodeAttr(tmp[i], 'mgt'); + // If it is zvm + if (mgt == 'zvm') { + // Add IPL input + optsList.append('
                      '); + break; + } + } + + // Generate tooltips + netbootForm.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" + } + }); + + /** + * Ok + */ + var okBtn = createButton('Ok'); + okBtn.css({ + 'width': '80px', + 'display': 'block' + }); + okBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + // Check inputs + var ready = true; + var inputs = $("#" + newTabId + " input[type='text']:visible"); + for ( var i = 0; i < inputs.length; i++) { + if (!inputs.eq(i).val()) { + inputs.eq(i).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + inputs.eq(i).css('border', 'solid #BDBDBD 1px'); + } + } + + // Generate arguments + var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); + var optStr = ''; + var opt; + for ( var i = 0; i < chkBoxes.length; i++) { + opt = chkBoxes.eq(i).attr('name'); + optStr += '-' + opt; + + // If it is the boot order + if (opt == 's') { + // Get the boot order + optStr += ';' + $('#' + newTabId + ' input[name=bootOrder]').val(); + } + + // Append ; to end of string + if (i < (chkBoxes.length - 1)) { + optStr += ';'; + } + } + + // If no inputs are empty + if (ready) { + // Get nodes + var tgts = $('#' + newTabId + ' input[name=target]').val(); + + // Get IPL address + var ipl = $('#' + newTabId + ' input[name=ipl]'); + if (ipl) { + optStr += 'ipl=' + ipl.val(); + } + + // Disable all inputs and Ok button + $('#' + newTabId + ' input').attr('disabled', 'disabled'); + $(this).attr('disabled', 'true'); + + /** + * (1) Boot to network + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rnetboot', + tgt : tgts, + args : optStr, + msg : 'out=' + statBarId + ';cmd=rnetboot;tgt=' + tgts + }, + + success : function(data) { + data = decodeRsp(data); + updateStatusBar(data); + } + }); + + // Show status bar + statusBar.show(); + } else { + // Show warning message + var warn = createWarnBar('Please provide a value for each missing field.'); + warn.prependTo($(this).parents('.ui-tabs-panel')); + } + }); + netbootForm.append(okBtn); + + // Append to discover tab + tab.add(newTabId, 'Boot', netbootForm, true); + + // Select new tab + tab.select(newTabId); } \ No newline at end of file diff --git a/xCAT-UI/js/nodes/rscan.js b/xCAT-UI/js/nodes/rscan.js index 5c9585274..06fdbff09 100644 --- a/xCAT-UI/js/nodes/rscan.js +++ b/xCAT-UI/js/nodes/rscan.js @@ -1,171 +1,174 @@ -/** - * Load rscan page - * - * @param tgtNodes Targets to run rscan against - */ -function loadRscanPage(tgtNodes) { - // Get node OS - var osHash = new Object(); - var nodes = tgtNodes.split(','); - for (var i in nodes) { - var os = getNodeAttr(nodes[i], 'os'); - var osBase = os.match(/[a-zA-Z]+/); - if (osBase) { - nodes[osBase] = 1; - } - } - - // Get nodes tab - var tab = getNodesTab(); - - // Generate new tab ID - var inst = 0; - var newTabId = 'rscanTab' + inst; - while ($('#' + newTabId).length) { - // If one already exists, generate another one - inst = inst + 1; - newTabId = 'rscanTab' + inst; - } - - // Create rscan form - var rscanForm = $('
                      '); - - // Create status bar - var statBarId = 'rscanStatusBar' + inst; - var statBar = createStatusBar(statBarId).hide(); - - // Create loader - var loader = createLoader('rscanLoader'); - statBar.find('div').append(loader); - - // Create info bar - var infoBar = createInfoBar('Collects node information from one or more hardware control points'); - rscanForm.append(statBar, infoBar); - - // Create VM fieldset - var vmFS = $('
                      '); - var vmLegend = $('Virtual Machine'); - vmFS.append(vmLegend); - rscanForm.append(vmFS); - - var vmAttr = $('
                      '); - vmFS.append($('
                      ')); - vmFS.append(vmAttr); - - // Create options fieldset - var optionsFS = $('
                      '); - var optionsLegend = $('Options'); - optionsFS.append(optionsLegend); - rscanForm.append(optionsFS); - - var optionsAttr = $('
                      '); - optionsFS.append($('
                      ')); - optionsFS.append(optionsAttr); - - // Create target node or group input - var target = $('
                      '); - vmAttr.append(target); - - // Create options - var optsList = $('
                        '); - optionsAttr.append(optsList); - - optsList.append('
                      • Updates and then prints out node definitions in the xCAT database for CEC/BPA
                      • '); - optsList.append('
                      • Writes output to xCAT database
                      • '); - optsList.append('
                      • XML format
                      • '); - optsList.append('
                      • Stanza formated output
                      • '); - - // Generate tooltips - rscanForm.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" - } - }); - - /** - * Ok - */ - var okBtn = createButton('Ok'); - okBtn.css({ - 'width': '80px', - 'display': 'block' - }); - okBtn.bind('click', function(event) { - // Remove any warning messages - $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); - - // Check inputs - var ready = true; - var inputs = $("#" + newTabId + " input[type='text']"); - for ( var i = 0; i < inputs.length; i++) { - if (!inputs.eq(i).val()) { - inputs.eq(i).css('border', 'solid #FF0000 1px'); - ready = false; - } else { - inputs.eq(i).css('border', 'solid #BDBDBD 1px'); - } - } - - // Generate arguments - var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); - var optStr = ''; - var opt; - for ( var i = 0; i < chkBoxes.length; i++) { - opt = chkBoxes.eq(i).attr('name'); - optStr += '-' + opt; - - // Append ; to end of string - if (i < (chkBoxes.length - 1)) { - optStr += ';'; - } - } - - // If no inputs are empty - if (ready) { - // Get nodes - var tgts = $('#' + newTabId + ' input[name=target]').val(); - - // Disable all inputs and Ok button - $('#' + newTabId + ' input').attr('disabled', 'disabled'); - $(this).attr('disabled', 'true'); - - /** - * (1) Scan - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'rscan', - tgt : tgts, - args : optStr, - msg : 'out=' + statBarId + ';cmd=rscan;tgt=' + tgts - }, - - success : updateStatusBar - }); - - // Show status bar - statBar.show(); - } else { - // Show warning message - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this).parents('.ui-tabs-panel')); - } - }); - rscanForm.append(okBtn); - - // Append to discover tab - tab.add(newTabId, 'Scan', rscanForm, true); - - // Select new tab - tab.select(newTabId); +/** + * Load rscan page + * + * @param tgtNodes Targets to run rscan against + */ +function loadRscanPage(tgtNodes) { + // Get node OS + var osHash = new Object(); + var nodes = tgtNodes.split(','); + for (var i in nodes) { + var os = getNodeAttr(nodes[i], 'os'); + var osBase = os.match(/[a-zA-Z]+/); + if (osBase) { + nodes[osBase] = 1; + } + } + + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'rscanTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'rscanTab' + inst; + } + + // Create rscan form + var rscanForm = $('
                        '); + + // Create status bar + var statBarId = 'rscanStatusBar' + inst; + var statBar = createStatusBar(statBarId).hide(); + + // Create loader + var loader = createLoader('rscanLoader'); + statBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('Collects node information from one or more hardware control points'); + rscanForm.append(statBar, infoBar); + + // Create VM fieldset + var vmFS = $('
                        '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + rscanForm.append(vmFS); + + var vmAttr = $('
                        '); + vmFS.append($('
                        ')); + vmFS.append(vmAttr); + + // Create options fieldset + var optionsFS = $('
                        '); + var optionsLegend = $('Options'); + optionsFS.append(optionsLegend); + rscanForm.append(optionsFS); + + var optionsAttr = $('
                        '); + optionsFS.append($('
                        ')); + optionsFS.append(optionsAttr); + + // Create target node or group input + var target = $('
                        '); + vmAttr.append(target); + + // Create options + var optsList = $('
                          '); + optionsAttr.append(optsList); + + optsList.append('
                        • Updates and then prints out node definitions in the xCAT database for CEC/BPA
                        • '); + optsList.append('
                        • Writes output to xCAT database
                        • '); + optsList.append('
                        • XML format
                        • '); + optsList.append('
                        • Stanza formated output
                        • '); + + // Generate tooltips + rscanForm.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" + } + }); + + /** + * Ok + */ + var okBtn = createButton('Ok'); + okBtn.css({ + 'width': '80px', + 'display': 'block' + }); + okBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + + // Check inputs + var ready = true; + var inputs = $("#" + newTabId + " input[type='text']"); + for ( var i = 0; i < inputs.length; i++) { + if (!inputs.eq(i).val()) { + inputs.eq(i).css('border', 'solid #FF0000 1px'); + ready = false; + } else { + inputs.eq(i).css('border', 'solid #BDBDBD 1px'); + } + } + + // Generate arguments + var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); + var optStr = ''; + var opt; + for ( var i = 0; i < chkBoxes.length; i++) { + opt = chkBoxes.eq(i).attr('name'); + optStr += '-' + opt; + + // Append ; to end of string + if (i < (chkBoxes.length - 1)) { + optStr += ';'; + } + } + + // If no inputs are empty + if (ready) { + // Get nodes + var tgts = $('#' + newTabId + ' input[name=target]').val(); + + // Disable all inputs and Ok button + $('#' + newTabId + ' input').attr('disabled', 'disabled'); + $(this).attr('disabled', 'true'); + + /** + * (1) Scan + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rscan', + tgt : tgts, + args : optStr, + msg : 'out=' + statBarId + ';cmd=rscan;tgt=' + tgts + }, + + success : function(data) { + data = decodeRsp(data); + updateStatusBar(data); + } + }); + + // Show status bar + statBar.show(); + } else { + // Show warning message + var warn = createWarnBar('Please provide a value for each missing field.'); + warn.prependTo($(this).parents('.ui-tabs-panel')); + } + }); + rscanForm.append(okBtn); + + // Append to discover tab + tab.add(newTabId, 'Scan', rscanForm, true); + + // Select new tab + tab.select(newTabId); } \ No newline at end of file diff --git a/xCAT-UI/js/nodes/updatenode.js b/xCAT-UI/js/nodes/updatenode.js index 943972e8e..d0a177a40 100644 --- a/xCAT-UI/js/nodes/updatenode.js +++ b/xCAT-UI/js/nodes/updatenode.js @@ -1,403 +1,409 @@ -/** - * Load updatenode page - * - * @param tgtNodes Targets to run updatenode against - */ -function loadUpdatenodePage(tgtNodes) { - // Get OS images - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : 'osimage', - msg : '' - }, - - success : setOSImageCookies - }); - - // Get node OS - var osHash = new Object(); - var nodes = tgtNodes.split(','); - for (var i in nodes) { - var os = getNodeAttr(nodes[i], 'os'); - var osBase = os.match(/[a-zA-Z]+/); - if (osBase) { - nodes[osBase] = 1; - } - } - - // Get nodes tab - var tab = getNodesTab(); - - // Generate new tab ID - var inst = 0; - var newTabId = 'updatenodeTab' + inst; - while ($('#' + newTabId).length) { - // If one already exists, generate another one - inst = inst + 1; - newTabId = 'updatenodeTab' + inst; - } - - // Create rscan form - var updatenodeForm = $('
                          '); - - // Create status bar - var statBarId = 'updatenodeStatusBar' + inst; - var statusBar = createStatusBar(statBarId).hide(); - - // Create loader - var loader = createLoader('updatenodeLoader'); - statusBar.find('div').append(loader); - - // Create info bar - var infoBar = createInfoBar('Update nodes in an xCAT environment'); - updatenodeForm.append(statusBar, infoBar); - - // Create VM fieldset - var vmFS = $('
                          '); - var vmLegend = $('Virtual Machine'); - vmFS.append(vmLegend); - updatenodeForm.append(vmFS); - - var vmAttr = $('
                          '); - vmFS.append($('
                          ')); - vmFS.append(vmAttr); - - // Create options fieldset - var optionsFS = $('
                          '); - var optionsLegend = $('Options'); - optionsFS.append(optionsLegend); - updatenodeForm.append(optionsFS); - - var optionsAttr = $('
                          '); - optionsFS.append($('
                          ')); - optionsFS.append(optionsAttr); - - // Create target node or group input - var tgt = $('
                          '); - vmAttr.append(tgt); - - // Create options - var optionsList = $('
                            '); - optionsAttr.append(optionsList); - - // Create update all software checkbox (only AIX) - if (osHash['AIX']) { - var updateAllOption = $('
                          • '); - var updateAllChkBox = $(''); - updateAllOption.append(updateAllChkBox); - optionsList.append(updateAllOption); - updateAllOption.append('Install or update all software contained in the source directory'); - - // Create source directory input - var allSwScrDirectory = $('
                          • '); - // Browse server directory and files - var allSWSrcDirBrowse = createButton('Browse'); - allSWSrcDirBrowse.serverBrowser({ - onSelect : function(path) { - $('#allSwSrcDirectory').val(path); - }, - onLoad : function() { - return $('#allSwSrcDirectory').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [ { - text : 'Install', - image : 'desktop.png', - path : '/install' - } ], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - allSwScrDirectory.append(allSWSrcDirBrowse); - allSwScrDirectory.hide(); - optionsList.append(allSwScrDirectory); - - // Show source directory when checked - updateAllChkBox.bind('click', function(event) { - if ($(this).is(':checked')) { - allSwScrDirectory.show(); - } else { - allSwScrDirectory.hide(); - } - }); - } - - // Create update software checkbox - var updateOption = $('
                          • '); - var updateChkBox = $(''); - optionsList.append(updateOption); - updateOption.append(updateChkBox); - updateOption.append('Update existing software'); - - // Create source directory input - var scrDirectory = $('
                          • '); - // Browse server directory and files - var srcDirBrowse = createButton('Browse'); - srcDirBrowse.serverBrowser({ - onSelect : function(path) { - $('#srcDirectory').val(path); - }, - onLoad : function() { - return $('#srcDirectory').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [ { - text : 'Install', - image : 'desktop.png', - path : '/install' - } ], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - scrDirectory.append(srcDirBrowse); - scrDirectory.hide(); - optionsList.append(scrDirectory); - - // Create other packages input - var otherPkgs = $('
                          • '); - otherPkgs.hide(); - optionsList.append(otherPkgs); - - // Create RPM flags input (only AIX) - var aixRpmFlags = $('
                          • '); - aixRpmFlags.hide(); - optionsList.append(aixRpmFlags); - - // Create installp flags input (only AIX) - var aixInstallPFlags = $('
                          • '); - aixInstallPFlags.hide(); - optionsList.append(aixInstallPFlags); - - // Create emgr flags input (only AIX) - var aixEmgrFlags = $('
                          • '); - aixEmgrFlags.hide(); - optionsList.append(aixEmgrFlags); - - // Show flags when checked - updateChkBox.bind('click', function(event) { - if ($(this).is(':checked')) { - scrDirectory.show(); - otherPkgs.show(); - if (osHash['AIX']) { - aixRpmFlags.show(); - aixInstallPFlags.show(); - aixEmgrFlags.show(); - } - } else { - scrDirectory.hide(); - otherPkgs.hide(); - if (osHash['AIX']) { - aixRpmFlags.hide(); - aixInstallPFlags.hide(); - aixEmgrFlags.hide(); - } - } - }); - - // Create postscripts input - var postOption = $('
                          • '); - var postChkBox = $(''); - optionsList.append(postOption); - postOption.append(postChkBox); - postOption.append('Run postscripts'); - var postscripts = $('
                          • '); - postscripts.hide(); - optionsList.append(postscripts); - - // Show alternate source directory when checked - postChkBox.bind('click', function(event) { - if ($(this).is(':checked')) { - postscripts.show(); - } else { - postscripts.hide(); - } - }); - optionsList.append('
                          • Distribute and synchronize files
                          • '); - optionsList.append('
                          • Update the ssh keys and host keys for the service nodes and compute nodes
                          • '); - - // Create update OS checkbox - if (!osHash['AIX']) { - var osOption = $('
                          • '); - var osChkBox = $(''); - optionsList.append(osOption); - osOption.append(osChkBox); - osOption.append('Update the operating system'); - - var os = $('
                          • ').hide(); - var osLabel = $(''); - var osInput = $(''); - osInput.one('focus', function(){ - var tmp = $.cookie('xcat_osvers'); - if (tmp) { - // Turn on auto complete - $(this).autocomplete({ - source: tmp.split(',') - }); - } - }); - os.append(osLabel); - os.append(osInput); - optionsList.append(os); - - // Show alternate source directory when checked - osChkBox.bind('click', function(event) { - if ($(this).is(':checked')) { - os.show(); - } else { - os.hide(); - } - }); - } - - // Generate tooltips - updatenodeForm.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" - } - }); - - /** - * Ok - */ - var updateBtn = createButton('Update'); - updateBtn.css({ - 'width': '80px', - 'display': 'block' - }); - updateBtn.bind('click', function(event) { - // Remove any warning messages - $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); - var ready = true; - - // Generate arguments - var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); - var optionsStr = ''; - var option; - for ( var i = 0; i < chkBoxes.length; i++) { - option = chkBoxes.eq(i).attr('name'); - optionsStr += '-' + option; - - // If update all software is checked - if (option == 'S') { - var srcDir = $('#' + newTabId + ' input[name=allSwSrcDirectory]').val(); - if (srcDir) { - optionsStr += ';-d ' + srcDir; - } - } - - // If update software is checked - if (option == 'S') { - // Get source directory - var srcDirectory = $('#' + newTabId + ' input[name=srcDirectory]').val(); - if (srcDirectory) { - optionsStr += ';-d;' + srcDirectory; - } - - // Get otherpkgs - var otherpkgs = $('#' + newTabId + ' input[name=otherpkgs]').val(); - if (otherpkgs) { - optionsStr += ';otherpkgs=' + otherpkgs; - } - - // Get rpm_flags - var rpm_flags = $('#' + newTabId + ' input[name=rpm_flags]').val(); - if (rpm_flags) { - optionsStr += ';rpm_flags=' + rpm_flags; - } - - // Get installp_flags - var installp_flags = $('#' + newTabId + ' input[name=installp_flags]').val(); - if (installp_flags) { - optionsStr += ';installp_flags=' + installp_flags; - } - - // Get emgr_flags - var emgr_flags = $('#' + newTabId + ' input[name=emgr_flags]').val(); - if (emgr_flags) { - optionsStr += ';emgr_flags=' + emgr_flags; - } - } - - // If postscripts is checked - if (option == 'P') { - // Get postscripts - optionsStr += ';' + $('#' + newTabId + ' input[name=postscripts]').val(); - } - - // If operating system is checked - if (option == 'o') { - // Get the OS - optionsStr += ';' + $('#' + newTabId + ' input[name=os]').val(); - } - - // Append ; to end of string - if (i < (chkBoxes.length - 1)) { - optionsStr += ';'; - } - } - - // If no inputs are empty - if (ready) { - // Get nodes - var tgts = $('#' + newTabId + ' input[name=target]').val(); - - // Disable all inputs and Ok button - $('#' + newTabId + ' input').attr('disabled', 'disabled'); - $(this).attr('disabled', 'true'); - - /** - * (1) Boot to network - */ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'updatenode', - tgt : tgts, - args : optionsStr, - msg : 'out=' + statBarId + ';cmd=updatenode;tgt=' + tgts - }, - - success : updateStatusBar - }); - - // Show status bar - statusBar.show(); - } else { - // Show warning message - var warn = createWarnBar('You are missing some values'); - warn.prependTo($(this).parents('.ui-tabs-panel')); - } - }); - updatenodeForm.append(updateBtn); - - // Append to discover tab - tab.add(newTabId, 'Update', updatenodeForm, true); - - // Select new tab - tab.select(newTabId); +/** + * Load updatenode page + * + * @param tgtNodes Targets to run updatenode against + */ +function loadUpdatenodePage(tgtNodes) { + // Get OS images + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'osimage', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setOSImageCookies(data); + } + }); + + // Get node OS + var osHash = new Object(); + var nodes = tgtNodes.split(','); + for (var i in nodes) { + var os = getNodeAttr(nodes[i], 'os'); + var osBase = os.match(/[a-zA-Z]+/); + if (osBase) { + nodes[osBase] = 1; + } + } + + // Get nodes tab + var tab = getNodesTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'updatenodeTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'updatenodeTab' + inst; + } + + // Create rscan form + var updatenodeForm = $('
                            '); + + // Create status bar + var statBarId = 'updatenodeStatusBar' + inst; + var statusBar = createStatusBar(statBarId).hide(); + + // Create loader + var loader = createLoader('updatenodeLoader'); + statusBar.find('div').append(loader); + + // Create info bar + var infoBar = createInfoBar('Update nodes in an xCAT environment'); + updatenodeForm.append(statusBar, infoBar); + + // Create VM fieldset + var vmFS = $('
                            '); + var vmLegend = $('Virtual Machine'); + vmFS.append(vmLegend); + updatenodeForm.append(vmFS); + + var vmAttr = $('
                            '); + vmFS.append($('
                            ')); + vmFS.append(vmAttr); + + // Create options fieldset + var optionsFS = $('
                            '); + var optionsLegend = $('Options'); + optionsFS.append(optionsLegend); + updatenodeForm.append(optionsFS); + + var optionsAttr = $('
                            '); + optionsFS.append($('
                            ')); + optionsFS.append(optionsAttr); + + // Create target node or group input + var tgt = $('
                            '); + vmAttr.append(tgt); + + // Create options + var optionsList = $('
                              '); + optionsAttr.append(optionsList); + + // Create update all software checkbox (only AIX) + if (osHash['AIX']) { + var updateAllOption = $('
                            • '); + var updateAllChkBox = $(''); + updateAllOption.append(updateAllChkBox); + optionsList.append(updateAllOption); + updateAllOption.append('Install or update all software contained in the source directory'); + + // Create source directory input + var allSwScrDirectory = $('
                            • '); + // Browse server directory and files + var allSWSrcDirBrowse = createButton('Browse'); + allSWSrcDirBrowse.serverBrowser({ + onSelect : function(path) { + $('#allSwSrcDirectory').val(path); + }, + onLoad : function() { + return $('#allSwSrcDirectory').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [ { + text : 'Install', + image : 'desktop.png', + path : '/install' + } ], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + allSwScrDirectory.append(allSWSrcDirBrowse); + allSwScrDirectory.hide(); + optionsList.append(allSwScrDirectory); + + // Show source directory when checked + updateAllChkBox.bind('click', function(event) { + if ($(this).is(':checked')) { + allSwScrDirectory.show(); + } else { + allSwScrDirectory.hide(); + } + }); + } + + // Create update software checkbox + var updateOption = $('
                            • '); + var updateChkBox = $(''); + optionsList.append(updateOption); + updateOption.append(updateChkBox); + updateOption.append('Update existing software'); + + // Create source directory input + var scrDirectory = $('
                            • '); + // Browse server directory and files + var srcDirBrowse = createButton('Browse'); + srcDirBrowse.serverBrowser({ + onSelect : function(path) { + $('#srcDirectory').val(path); + }, + onLoad : function() { + return $('#srcDirectory').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [ { + text : 'Install', + image : 'desktop.png', + path : '/install' + } ], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + scrDirectory.append(srcDirBrowse); + scrDirectory.hide(); + optionsList.append(scrDirectory); + + // Create other packages input + var otherPkgs = $('
                            • '); + otherPkgs.hide(); + optionsList.append(otherPkgs); + + // Create RPM flags input (only AIX) + var aixRpmFlags = $('
                            • '); + aixRpmFlags.hide(); + optionsList.append(aixRpmFlags); + + // Create installp flags input (only AIX) + var aixInstallPFlags = $('
                            • '); + aixInstallPFlags.hide(); + optionsList.append(aixInstallPFlags); + + // Create emgr flags input (only AIX) + var aixEmgrFlags = $('
                            • '); + aixEmgrFlags.hide(); + optionsList.append(aixEmgrFlags); + + // Show flags when checked + updateChkBox.bind('click', function(event) { + if ($(this).is(':checked')) { + scrDirectory.show(); + otherPkgs.show(); + if (osHash['AIX']) { + aixRpmFlags.show(); + aixInstallPFlags.show(); + aixEmgrFlags.show(); + } + } else { + scrDirectory.hide(); + otherPkgs.hide(); + if (osHash['AIX']) { + aixRpmFlags.hide(); + aixInstallPFlags.hide(); + aixEmgrFlags.hide(); + } + } + }); + + // Create postscripts input + var postOption = $('
                            • '); + var postChkBox = $(''); + optionsList.append(postOption); + postOption.append(postChkBox); + postOption.append('Run postscripts'); + var postscripts = $('
                            • '); + postscripts.hide(); + optionsList.append(postscripts); + + // Show alternate source directory when checked + postChkBox.bind('click', function(event) { + if ($(this).is(':checked')) { + postscripts.show(); + } else { + postscripts.hide(); + } + }); + optionsList.append('
                            • Distribute and synchronize files
                            • '); + optionsList.append('
                            • Update the ssh keys and host keys for the service nodes and compute nodes
                            • '); + + // Create update OS checkbox + if (!osHash['AIX']) { + var osOption = $('
                            • '); + var osChkBox = $(''); + optionsList.append(osOption); + osOption.append(osChkBox); + osOption.append('Update the operating system'); + + var os = $('
                            • ').hide(); + var osLabel = $(''); + var osInput = $(''); + osInput.one('focus', function(){ + var tmp = $.cookie('xcat_osvers'); + if (tmp) { + // Turn on auto complete + $(this).autocomplete({ + source: tmp.split(',') + }); + } + }); + os.append(osLabel); + os.append(osInput); + optionsList.append(os); + + // Show alternate source directory when checked + osChkBox.bind('click', function(event) { + if ($(this).is(':checked')) { + os.show(); + } else { + os.hide(); + } + }); + } + + // Generate tooltips + updatenodeForm.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" + } + }); + + /** + * Ok + */ + var updateBtn = createButton('Update'); + updateBtn.css({ + 'width': '80px', + 'display': 'block' + }); + updateBtn.bind('click', function(event) { + // Remove any warning messages + $(this).parents('.ui-tabs-panel').find('.ui-state-error').remove(); + var ready = true; + + // Generate arguments + var chkBoxes = $("#" + newTabId + " input[type='checkbox']:checked"); + var optionsStr = ''; + var option; + for ( var i = 0; i < chkBoxes.length; i++) { + option = chkBoxes.eq(i).attr('name'); + optionsStr += '-' + option; + + // If update all software is checked + if (option == 'S') { + var srcDir = $('#' + newTabId + ' input[name=allSwSrcDirectory]').val(); + if (srcDir) { + optionsStr += ';-d ' + srcDir; + } + } + + // If update software is checked + if (option == 'S') { + // Get source directory + var srcDirectory = $('#' + newTabId + ' input[name=srcDirectory]').val(); + if (srcDirectory) { + optionsStr += ';-d;' + srcDirectory; + } + + // Get otherpkgs + var otherpkgs = $('#' + newTabId + ' input[name=otherpkgs]').val(); + if (otherpkgs) { + optionsStr += ';otherpkgs=' + otherpkgs; + } + + // Get rpm_flags + var rpm_flags = $('#' + newTabId + ' input[name=rpm_flags]').val(); + if (rpm_flags) { + optionsStr += ';rpm_flags=' + rpm_flags; + } + + // Get installp_flags + var installp_flags = $('#' + newTabId + ' input[name=installp_flags]').val(); + if (installp_flags) { + optionsStr += ';installp_flags=' + installp_flags; + } + + // Get emgr_flags + var emgr_flags = $('#' + newTabId + ' input[name=emgr_flags]').val(); + if (emgr_flags) { + optionsStr += ';emgr_flags=' + emgr_flags; + } + } + + // If postscripts is checked + if (option == 'P') { + // Get postscripts + optionsStr += ';' + $('#' + newTabId + ' input[name=postscripts]').val(); + } + + // If operating system is checked + if (option == 'o') { + // Get the OS + optionsStr += ';' + $('#' + newTabId + ' input[name=os]').val(); + } + + // Append ; to end of string + if (i < (chkBoxes.length - 1)) { + optionsStr += ';'; + } + } + + // If no inputs are empty + if (ready) { + // Get nodes + var tgts = $('#' + newTabId + ' input[name=target]').val(); + + // Disable all inputs and Ok button + $('#' + newTabId + ' input').attr('disabled', 'disabled'); + $(this).attr('disabled', 'true'); + + /** + * (1) Boot to network + */ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'updatenode', + tgt : tgts, + args : optionsStr, + msg : 'out=' + statBarId + ';cmd=updatenode;tgt=' + tgts + }, + + success : function(data) { + data = decodeRsp(data); + updateStatusBar(data); + } + }); + + // Show status bar + statusBar.show(); + } else { + // Show warning message + var warn = createWarnBar('You are missing some values'); + warn.prependTo($(this).parents('.ui-tabs-panel')); + } + }); + updatenodeForm.append(updateBtn); + + // Append to discover tab + tab.add(newTabId, 'Update', updatenodeForm, true); + + // Select new tab + tab.select(newTabId); } \ No newline at end of file diff --git a/xCAT-UI/js/provision/images.js b/xCAT-UI/js/provision/images.js index d1a6f174d..fd4967321 100644 --- a/xCAT-UI/js/provision/images.js +++ b/xCAT-UI/js/provision/images.js @@ -1,1435 +1,1462 @@ -/** - * Global variables - */ -var origAttrs = new Object(); // Original image attributes -var defAttrs; // Definable image attributes -var imgTableId = 'imagesDatatable'; // Images datatable ID -var softwareList = { - "rsct" : ["rsct.core.utils", "rsct.core", "src"], - "pe" : ["IBMJava2-142-ppc64-JRE", "ibm_lapi_ip_rh6p", "ibm_lapi_us_rh6p", "IBM_pe_license", "ibm_pe_rh6p", "ppe_pdb_ppc64_rh600", "sci_ppc_32bit_rh600", "sci_ppc_64bit_rh600", "vac.cmp", - "vac.lib", "vac.lic", "vacpp.cmp", "vacpp.help.pdf", "vacpp.lib", "vacpp.man", "vacpp.rte", "vacpp.rte.lnk", "vacpp.samples", "xlf.cmp", "xlf.help.pdf", "xlf.lib", "xlf.lic", "xlf.man", - "xlf.msg.rte", "xlf.rte", "xlf.rte.lnk", "xlf.samples", "xlmass.lib", "xlsmp.lib", "xlsmp.msg.rte", "xlsmp.rte"], - "gpfs" : ["gpfs.base", "gpfs.gpl", "gpfs.gplbin", "gpfs.msg.en_US"], - "essl" : ["essl.3232.rte", "essl.3264.rte", "essl.6464.rte", "essl.common", "essl.license", "essl.man", "essl.msg", "essl.rte", "ibm-java2", "pessl.common", "pessl.license", "pessl.man", - "pessl.msg", "pessl.rte.ppe"], - "loadl" : ["IBMJava2", "LoadL-full-license-RH6", "LoadL-resmgr-full-RH6", "LoadL-scheduler-full-RH6"], - "ganglia" : ["rrdtool", "ganglia", "ganglia-gmetad", "ganglia-gmond"], - "base" : ["createrepo"] -}; - -/** - * Load images page - */ -function loadImagesPage() { - // Set padding for images page - $('#imagesTab').css('padding', '20px 60px'); - - // Get images within the database - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsdef', - tgt : '', - args : '-t;osimage;-l', - msg : '' - }, - - success : loadImages - }); -} - -/** - * Load images within the database - * - * @param data Data returned from HTTP request - */ -function loadImages(data) { - // Data returned - var rsp = data.rsp; - if (rsp[0].indexOf('Could not find any object definitions') > -1) { - rsp = new Array(); - } - - // Image attributes hash - var attrs = new Object(); - // Image attributes - var headers = new Object(); - - // Clear hash table containing image attributes - origAttrs = ''; - - var image; - var args; - for (var i in rsp) { - // Get the image - var pos = rsp[i].indexOf('Object name:'); - if (pos > -1) { - var temp = rsp[i].split(': '); - image = jQuery.trim(temp[1]); - - // Create a hash for the image attributes - attrs[image] = new Object(); - i++; - } - - // Get key and value - args = rsp[i].split('='); - var key = jQuery.trim(args[0]); - var val = jQuery.trim(args[1]); - - // Create a hash table - attrs[image][key] = val; - headers[key] = 1; - } - - // Save attributes in hash table - origAttrs = attrs; - - // Sort headers - var sorted = new Array(); - for (var key in headers) { - sorted.push(key); - } - sorted.sort(); - - // Add column for check box and image name - sorted.unshift('', 'imagename'); - - // Create a datatable - var dTable = new DataTable(imgTableId); - dTable.init(sorted); - - // Go through each image - for (var img in attrs) { - // Create a row - var row = new Array(); - // Create a check box - var checkBx = ''; - // Push in checkbox and image name - row.push(checkBx, img); - - // Go through each header - for (var i = 2; i < sorted.length; i++) { - // Add the node attributes to the row - var key = sorted[i]; - var val = attrs[img][key]; - if (val) { - row.push(val); - } else { - row.push(''); - } - } - - // Add the row to the table - dTable.add(row); - } - - // Clear the tab before inserting the table - $('#imagesTab').children().remove(); - - // Create info bar for images tab - var info = createInfoBar('Double click on a cell to edit. Click outside the table to save changes. Hit the Escape key to ignore changes.'); - $('#imagesTab').append(info); - - /** - * The following actions are available for images: - * copy Linux distribution and edit image properties - */ - - // Copy CD into install directory - var copyCDLnk = $('Copy CD'); - copyCDLnk.click(function() { - openCopyCdDialog(); - }); - - // Generate stateless or statelite image - var generateLnk = $('Generate image'); - generateLnk.click(function() { - loadCreateImage(); - }); - - // Edit image attributes - var editLnk = $('Edit'); - editLnk.click(function() { - var tgtImages = getNodesChecked(imgTableId).split(','); - if (tgtImages) { - for (var i in tgtImages) { - openEditImagePage(tgtImages[i]); - } - } - }); - - // Add a row - var addLnk = $('Add'); - addLnk.click(function() { - openAddImageDialog(); - }); - - // Remove a row - var removeLnk = $('Remove'); - removeLnk.click(function() { - var images = getNodesChecked(imgTableId); - if (images) { - confirmImageDeleteDialog(images); - } - }); - - // Refresh image table - var refreshLnk = $('Refresh'); - refreshLnk.click(function() { - // Get images within the database - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsdef', - tgt : '', - args : '-t;osimage;-l', - msg : '' - }, - - success : loadImages - }); - }); - - // Insert table - $('#imagesTab').append(dTable.object()); - - // Turn table into a datatable - var myDataTable = $('#' + imgTableId).dataTable({ - 'iDisplayLength': 50, - 'bLengthChange': false, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - - // Set datatable width - $('#' + imgTableId + '_wrapper').css({ - 'width': '880px' - }); - - // Actions - var actionBar = $('
                              ').css("width", "450px"); - var advancedLnk = 'Advanced'; - var advancedMenu = createMenu([copyCDLnk, generateLnk]); - - // Create an action menu - var actionsMenu = createMenu([refreshLnk, addLnk, editLnk, removeLnk, [advancedLnk, advancedMenu]]); - actionsMenu.superfish(); - actionsMenu.css('display', 'inline-block'); - actionBar.append(actionsMenu); - - // Set correct theme for action menu - actionsMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + imgTableId + '_wrapper').prepend(menuDiv); - menuDiv.append(actionBar); - $('#' + imgTableId + '_filter').appendTo(menuDiv); - - /** - * Enable editable columns - */ - - // Do not make 1st or 2nd columns editable - $('#' + imgTableId + ' td:not(td:nth-child(1),td:nth-child(2))').editable( - function(value, settings) { - // Get column index - var colPos = this.cellIndex; - - // Get row index - var dTable = $('#' + imgTableId).dataTable(); - var rowPos = dTable.fnGetPosition(this.parentNode); - - // Update datatable - dTable.fnUpdate(value, rowPos, colPos); - - // Get image name - var image = $(this).parent().find('td:eq(1)').text(); - - // Get table headers - var headers = $('#' + imgTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); - - // Get attribute name - var attrName = jQuery.trim(headers.eq(colPos).text()); - // Get column value - var value = $(this).text(); - // Build argument - var args = attrName + '=' + value; - - // Send command to change image attributes - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chdef', - tgt : '', - args : '-t;osimage;-o;' + image + ';' + args, - msg : 'out=imagesTab;tgt=' + image - }, - - success: showChdefOutput - }); - - return value; - }, { - onblur : 'submit', // Clicking outside editable area submits changes - type : 'textarea', // Input type to use - placeholder: ' ', - event : "dblclick", // Double click and edit - height : '30px' // The height of the text area - }); - - // Get definable node attributes - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'lsdef', - tgt : '', - args : '-t;osimage;-h', - msg : '' - }, - - success : setImageDefAttrs - }); -} - -/** - * Open dialog to confirm deleting image - * - * @param images Comma delimited image names - */ -function confirmImageDeleteDialog(images) { - // Make images list more readable - var dialogId = 'confirmImageRemove'; - var tmp = images.replace(new RegExp(',', 'g'), ', '); - var confirmDialog = $('
                              ' - + '

                              Are you sure you want to remove ' + tmp + '?

                              ' - + '
                              '); - - // Open dialog to confirm delete - confirmDialog.dialog({ - modal: true, - close: function(){ - $(this).remove(); - }, - title: 'Confirm', - width: 500, - buttons: { - "Ok": function(){ - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // Add image to xCAT - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'rmdef', - tgt : '', - args : '-t;osimage;-o;' + images, - msg : dialogId - }, - - success : updateImageDialog - }); - }, - "Cancel": function(){ - $(this).dialog("close"); - } - } - }); -} - -/** - * Open a dialog to add an image - */ -function openAddImageDialog() { - // Create dialog to add image - var dialogId = 'addImage'; - var addImageForm = $('
                              '); - - // Create info bar - var info = createInfoBar('Provide the following attributes for the image. The image name will be generated based on the attributes you will give.'); - - var imageFS = $('
                              '); - var imageLegend = $('Image'); - imageFS.append(imageLegend); - var imageAttr = $('
                              '); - imageFS.append($('
                              ')); - imageFS.append(imageAttr); - - var optionFS = $('
                              '); - var optionLegend = $('Options'); - optionFS.append(optionLegend); - var optionAttr = $('
                              '); - optionFS.append($('
                              ')); - optionFS.append(optionAttr); - - addImageForm.append(info, imageFS, optionFS); - - // Create inputs for image attributes - var imageName = $('
                              '); - var imageType = $('
                              '); - var architecture = $('
                              '); - var osName = $('
                              '); - var osVersion = $('
                              '); - var profile = $('
                              '); - var provisionMethod = $('
                              '); - var provisionSelect = $(''); - provisionMethod.append(provisionSelect); - - // Create inputs for optional attributes - var otherpkgDirectory = $('
                              '); - var otherpkgDirectoryInput = $(''); - otherpkgDirectory.append(otherpkgDirectoryInput); - otherpkgDirectoryInput.serverBrowser({ - onSelect : function(path) { - $('#addImage input[name="otherpkgdir"]').val(path); - }, - onLoad : function() { - return $('#addImage input[name="otherpkgdir"]').val(); - }, - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - var packageDirectory = $('
                              '); - var packageDirectoryInput = $(''); - packageDirectory.append(packageDirectoryInput); - packageDirectoryInput.serverBrowser({ - onSelect : function(path) { - $('#addImage input[name="pkgdir"]').val(path); - }, - onLoad : function() { - return $('#addImage input[name="pkgdir"]').val(); - }, - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - var packageList = $('
                              '); - var packageListInput = $(''); - packageList.append(packageListInput); - packageListInput.serverBrowser({ - onSelect : function(path) { - $('#addImage input[name="pkglist"]').val(path); - }, - onLoad : function() { - return $('#addImage input[name="pkglist"]').val(); - }, - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - var template = $('
                              '); - var templateInput = $(''); - template.append(templateInput); - templateInput.serverBrowser({ - onSelect : function(path) { - $('#addImage input[name="template"]').val(path); - }, - onLoad : function() { - return $('#addImage input[name="template"]').val(); - }, - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - - imageAttr.append(imageName, imageType, architecture, osName, osVersion, profile, provisionMethod); - optionAttr.append(otherpkgDirectory, packageDirectory, packageList, template); - - // Generate tooltips - addImageForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to add image - addImageForm.dialog({ - title:'Add image', - modal: true, - close: function(){ - $(this).remove(); - }, - beight: 400, - width: 600, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - // Get image attributes - var imageType = $(this).find('input[name="imagetype"]'); - var architecture = $(this).find('input[name="osarch"]'); - var osName = $(this).find('input[name="osname"]'); - var osVersion = $(this).find('input[name="osvers"]'); - var profile = $(this).find('input[name="profile"]'); - var provisionMethod = $(this).find('select[name="provmethod"]'); - - // Get optional image attributes - var otherpkgDirectory = $(this).find('input[name="otherpkgdir"]'); - var pkgDirectory = $(this).find('input[name="pkgdir"]'); - var pkgList = $(this).find('input[name="pkglist"]'); - var template = $(this).find('input[name="template"]'); - - // Check that image attributes are provided before continuing - var ready = 1; - var inputs = new Array(imageType, architecture, osName, osVersion, profile, provisionMethod); - for (var i in inputs) { - if (!inputs[i].val()) { - inputs[i].css('border-color', 'red'); - ready = 0; - } else - inputs[i].css('border-color', ''); - } - - // If inputs are not complete, show warning message - if (!ready) { - var warn = createWarnBar('Please provide a value for each missing field.'); - warn.prependTo($(this)); - } else { - // Override image name - $(this).find('input[name="imagename"]').val(osVersion.val() + '-' + architecture.val() + '-' + provisionMethod.val() + '-' + profile.val()); - var imageName = $(this).find('input[name="imagename"]'); - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // Create arguments to send via AJAX - var args = '-t;osimage;-o;' + imageName.val() + ';' + - 'imagetype=' + imageType.val() + ';' + - 'osarch=' + architecture.val() + ';' + - 'osname=' + osName.val() + ';' + - 'osvers=' + osVersion.val() + ';' + - 'profile=' + profile.val() + ';' + - 'provmethod=' + provisionMethod.val(); - - // Get optional attributes - if (otherpkgDirectory.val()) - args += ';otherpkgdir=' + otherpkgDirectory.val(); - if (pkgDirectory.val()) - args += ';pkgdir=' + pkgDirectory.val(); - if (pkgList.val()) - args += ';pkglist=' + pkgList.val(); - if (template.val()) - args += ';template=' + template.val(); - - // Add image to xCAT - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chdef', - tgt : '', - args : args, - msg : dialogId - }, - - success : updateImageDialog - }); - } - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Update image dialog - * - * @param data HTTP request data - */ -function updateImageDialog(data) { - var dialogId = data.msg; - var infoMsg; - - // Delete loader if one does exist - $('.ui-dialog #' + dialogId + ' img[src="images/loader.gif"]').remove(); - - // Create info message - if (jQuery.isArray(data.rsp)) { - infoMsg = ''; - - // If the data returned is more than 10 lines, get only the last line - var i, start; - if (data.rsp.length > 10) - start = data.rsp.length - 1; - else - start = 0; - - for (i = start; i < data.rsp.length; i++) - infoMsg += data.rsp[i] + '
                              '; - } else { - infoMsg = data.rsp; - } - - // Create info bar with close button - var infoBar = $('
                              ').css('margin', '5px 0px'); - var icon = $('').css({ - 'display': 'inline-block', - 'margin': '10px 5px' - }); - - // Create close button to close info bar - var close = $('').css({ - 'display': 'inline-block', - 'float': 'right' - }).click(function() { - $(this).parent().remove(); - }); - - var msg = $('

                              ' + infoMsg + '

                              ').css({ - 'display': 'inline-block', - 'width': '90%' - }); - - infoBar.append(icon, msg, close); - infoBar.prependTo($('.ui-dialog #' + dialogId)); -} - -/** - * Set definable image attributes - * - * @param data Data returned from HTTP request - */ -function setImageDefAttrs(data) { - // Clear hash table containing definable image attributes - defAttrs = new Array(); - - // Get definable attributes - var attrs = data.rsp[2].split(/\n/); - - // Go through each line - var attr, key, descr; - for (var i in attrs) { - attr = attrs[i]; - - // If the line is not empty - if (attr) { - // If the line has the attribute name - if (attr.indexOf(':') && attr.indexOf(' ')) { - // Get attribute name and description - key = jQuery.trim(attr.substring(0, attr.indexOf(':'))); - descr = jQuery.trim(attr.substring(attr.indexOf(':') + 1)); - descr = descr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']'); - - // Set hash table where key = attribute name and value = description - defAttrs[key] = descr; - } else { - // Append description to hash table - defAttrs[key] = defAttrs[key] + '\n' + attr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']'); - } - } // End of if - } // End of for -} - -/** - * Load create image page - */ -function loadCreateImage() { - // Get nodes tab - var tab = getProvisionTab(); - var tabId = 'createImageTab'; - - // Generate new tab ID - if ($('#' + tabId).size()) { - tab.select(tabId); - return; - } - - var imageOsVers = $.cookie("xcat_osvers").split(","); - var imageArch = $.cookie("xcat_osarchs").split(","); - var profiles = $.cookie("xcat_profiles").split(","); - - var createImgForm = $('
                              '); - var createImgFS = $('
                              ').append('Create Image'); - createImgForm.append(createImgFS); - - // Show info bar - var infoBar = createInfoBar('Specify the parameters for the image (stateless or statelite) you want to create, then click Create.'); - createImgFS.append(infoBar); - - // Drop down for OS versions - var osVerSelect = $(''); - for (var i in imageOsVers) - osVerSelect.append(''); - createImgFS.append($('
                              ').append(osVerSelect)); - - // Drop down for OS architectures - var imgSelect = $(''); - for (var i in imageArch) - imgSelect.append(''); - createImgFS.append($('
                              ').append(imgSelect)); - - // Netboot interface input - createImgFS.append($('
                              ')); - - // Profile selector - var profileSelect = $('' + - '' + - '' + - '
                              ')); - - // Create HPC software stack fieldset - createHpcFS(createImgForm); - - // The button used to create images is created here - var createImageBtn = createButton("Create"); - createImageBtn.bind('click', function(event) { - createImage(); - }); - - createImgForm.append(createImageBtn); - - // Add tab - tab.add(tabId, 'Create', createImgForm, true); - tab.select(tabId); - - // Check the selected OS version and OS arch for HPC stack - // If they are valid, show the HCP stack fieldset - hpcShow(); -} - -/** - * Create HPC fieldset - * - * @param container The container to hold the HPC fieldset - */ -function createHpcFS(container) { - var hpcFieldset = $('
                              '); - hpcFieldset.append('HPC Software Stack'); - - var str = 'Before selecting the software, you should have the following already completed on your xCAT cluster:

                              ' - + '1. If you are using the xCAT hierarchy, your service nodes are installed and running.
                              ' - + '2. Your compute nodes are defined in xCAT, and you have verified your hardware control capabilities, ' - + 'gathered MAC addresses, and done all the other necessary preparations for a diskless install.
                              ' - + '3. You should have a diskless image created with the base OS installed and verified it on at least one test node.
                              ' - + '4. You should install the software on the management node and copy all correponding packages into the location "/install/custom/otherpkgs/" based on ' - + 'these documents.
                              '; - hpcFieldset.append(createInfoBar(str)); - - // Advanced software - str = '
                              • GPFS
                              • ' + - '
                              • RSCT
                              • ' + - '
                              • PE
                              • ' + - '
                              • ESSl & PESSL
                              • ' + - '
                              ' + - '
                              • Ganglia
                              • ' + - '
                              '; - hpcFieldset.append(str); - - container.append($('
                              ').append(hpcFieldset)); -} - -/** - * Check the dependance for ESSL and start the software check for ESSL - * - * @param softwareObject The checkbox object of ESSL - */ -function esslCheck(softwareObject) { - var softwareName = softwareObject.name; - if (!$('#createImageTab input[name=pe]').attr('checked')) { - var warnBar = createWarnBar('You must first select the PE'); - $(':checkbox[name=essl]').attr("checked", false); - - // Clear existing warnings and append new warning - $('#hpcsoft .ui-state-error').remove(); - $('#hpcsoft').prepend(warnBar); - - return; - } else { - softwareCheck(softwareObject); - } -} - -/** - * Check the parameters for the HPC software - * - * @param softwareObject Checkbox object of the HPC software - * @return True if the checkbox is checked, false otherwise - */ -function softwareCheck(softwareObject) { - var softwareName = softwareObject.name; - $('#createImageTab #' + softwareName + 'li .ui-state-error').remove(); - $('#createImageTab #' + softwareName + 'li').append(createLoader()); - var cmdString = genRpmCmd(softwareName); - $.ajax( { - url : 'lib/systemcmd.php', - dataType : 'json', - data : { - cmd : cmdString, - msg : softwareName - }, - success : function(data) { - if (rpmCheck(data.rsp, data.msg)) { - genLsCmd(data.msg); - $.ajax( { - url : 'lib/systemcmd.php', - dataType : 'json', - data : { - cmd : genLsCmd(data.msg), - msg : data.msg - }, - success : rpmCopyCheck - }); - } - } - }); -} - -/** - * Check if the RPMs are copied to the special location - * - * @param data Data returned from HTTP request - */ -function rpmCopyCheck(data) { - // Remove the loading image - var errorStr = ''; - var softwareName = data.msg; - - // Check the return information - var reg = /.+:(.+): No such.*/; - var resultArray = data.rsp.split("\n"); - for ( var i in resultArray) { - var temp = reg.exec(resultArray[i]); - if (temp) { - // Find out the path and RPM name - var pos = temp[1].lastIndexOf('/'); - var path = temp[1].substring(0, pos); - var rpmName = temp[1].substring(pos + 1).replace('*', ''); - errorStr += 'copy ' + rpmName + ' to ' + path + '
                              '; - } - } - $('#createImageTab #' + softwareName + 'li').find('img').remove(); - - // No error, show the check image - if (!errorStr) { - var infoPart = '
                              '; - $('#createImageTab #' + softwareName + 'li').append(infoPart); - } else { - // Show the error message - errorStr = 'To install the RSCT on your compute node. You should:
                              ' + errorStr + '
                              '; - var warnBar = createWarnBar(errorStr); - $(':checkbox[name=' + softwareName + ']').attr("checked", false); - - // Clear existing warnings and append new warning - $('#hpcsoft .ui-state-error').remove(); - $('#hpcsoft').prepend(warnBar); - } -} - -/** - * Generate the RPM command for rpmcheck - * - * @param softwareName The name of the software - * @return The RPM command - */ -function genRpmCmd(softwareName) { - var cmdString; - cmdString = 'rpm -q '; - for (var i in softwareList[softwareName]) { - cmdString += softwareList[softwareName][i] + ' '; - } - - for (var i in softwareList['base']) { - cmdString += softwareList['base'][i] + ' '; - } - - return cmdString; -} - -/** - * Check if the RPMs for the HPC software are copied to the special location - * - * @param softwareName The name of the software - */ -function genLsCmd(softwareName) { - var osvers = $('#createImageTab #osvers').val(); - var osarch = $('#createImageTab #osarch').val(); - var path = '/install/post/otherpkgs/' + osvers + '/' + osarch + '/' + softwareName; - var checkCmd = 'ls '; - - for (var i in softwareList[softwareName]) { - checkCmd += path + '/' + softwareList[softwareName][i] + '*.rpm '; - } - checkCmd += '2>&1'; - - return checkCmd; -} - -/** - * Check if all RPMs are installed - * - * @param checkInfo 'rpm -q' output - * @return True if all RPMs are installed, false otherwise - */ -function rpmCheck(checkInfo, name) { - var errorStr = ''; - - var checkArray = checkInfo.split('\n'); - for (var i in checkArray) { - if (checkArray[i].indexOf('not install') != -1) { - errorStr += checkArray[i] + '
                              '; - } - } - - if (!errorStr) { - return true; - } - - errorStr = errorStr.substr(0, errorStr.length - 1); - $(':checkbox[name=' + name + ']').attr('checked', false); - - // Add the error - var warnBar = createWarnBar(errorStr); - $('#createImageTab #' + name + 'li').find('img').remove(); - - // Clear existing warnings and append new warning - $('#hpcsoft .ui-state-error').remove(); - $('#hpcsoft').prepend(warnBar); - - return; -} - -/** - * Check the option and decide whether to show the hpcsoft or not - */ -function hpcShow() { - // The current UI only supports RHELS 6 - // If you want to support all, delete the subcheck - if ($('#createImageTab #osvers').attr('value') != "rhels6" || $('#createImageTab #osarch').attr('value') != "ppc64" || $('#createImageTab #profile').attr('value') != "compute") { - $('#createImageTab #partlysupport').hide(); - } else { - $('#createImageTab #partlysupport').show(); - } -} - -/** - * Load set image properties page - * - * @param tgtImage Target image to set properties - */ -function openEditImagePage(tgtImage) { - // Get nodes tab - var tab = getProvisionTab(); - - // Generate new tab ID - var inst = 0; - var newTabId = 'editImageTab' + inst; - while ($('#' + newTabId).length) { - // If one already exists, generate another one - inst = inst + 1; - newTabId = 'editImageTab' + inst; - } - - // Open new tab - // Create set properties form - var setPropsForm = $('
                              '); - - // Create info bar - var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.'); - setPropsForm.append(infoBar); - - // Create an input for each definable attribute - var div, label, input, value; - var attrIndex = 0; - // Set node attribute - origAttrs[tgtImage]['imagename'] = tgtImage; - for (var key in defAttrs) { - // If an attribute value exists - if (origAttrs[tgtImage][key]) { - // Set the value - value = origAttrs[tgtImage][key]; - } else { - value = ''; - } - - // Create label and input for attribute - div = $('
                              ').css('display', 'inline'); - label = $('').css('vertical-align', 'middle'); - input = $('').css({ - 'margin-top': '5px', - 'float': 'none', - 'width': 'inherit' - }); - - // There is an element called groups that will override the defaults for the groups attribute. - // Hence, the input must have use CSS to override the float and width. - - // Split attributes into 2 per row - if (attrIndex > 0 && !(attrIndex % 2)) { - div.css('display', 'inline-block'); - } - - attrIndex++; - - // Create server browser - switch (key) { - case 'pkgdir': - input.serverBrowser({ - onSelect : function(path) { - $('#pkgdir').val(path); - }, - onLoad : function() { - return $('#pkgdir').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - break; - case 'otherpkgdir': - input.serverBrowser({ - onSelect : function(path) { - $('#otherpkgdir').val(path); - }, - onLoad : function() { - return $('#otherpkgdir').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - break; - case 'pkglist': - input.serverBrowser({ - onSelect : function(path) { - $('#pkglist').val(path); - }, - onLoad : function() { - return $('#pkglist').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/opt/xcat/share' // Limit user to only install directory - }); - break; - case 'otherpkglist': - input.serverBrowser({ - onSelect : function(path) { - $('#otherpkglist').val(path); - }, - onLoad : function() { - return $('#otherpkglist').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - break; - case 'template': - input.serverBrowser({ - onSelect : function(path) { - $('#template').val(path); - }, - onLoad : function() { - return $('#template').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [{ - text : 'Install', - image : 'desktop.png', - path : '/install' - }], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/opt/xcat/share' // Limit user to only install directory - }); - break; - default: - // Do nothing - } - - // Change border to blue onchange - input.bind('change', function(event) { - $(this).css('border-color', 'blue'); - }); - - div.append(label, input); - setPropsForm.append(div); - } - - // Change style for last division - div.css({ - 'display': 'block', - 'margin': '0px 0px 10px 0px' - }); - - // Generate tooltips - setPropsForm.find('div input[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 500, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - } - }); - - /** - * Save - */ - var saveBtn = createButton('Save'); - saveBtn.bind('click', function(event) { - // Get all inputs - var inputs = $('#' + newTabId + ' input'); - - // Go through each input - var args = ''; - var attrName, attrVal; - inputs.each(function(){ - // If the border color is blue - if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') { - // Change border color back to normal - $(this).css('border-color', ''); - - // Get attribute name and value - attrName = $(this).parent().find('label').text().replace(':', ''); - attrVal = $(this).val(); - - // Build argument string - if (args) { - // Handle subsequent arguments - args += ';' + attrName + '=' + attrVal; - } else { - // Handle the 1st argument - args += attrName + '=' + attrVal; - } - } - }); - - // Send command to change image attributes - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'chdef', - tgt : '', - args : '-t;osimage;-o;' + tgtImage + ';' + args, - msg : 'out=' + newTabId + ';tgt=' + tgtImage - }, - - success: showChdefOutput - }); - }); - setPropsForm.append(saveBtn); - - /** - * Cancel - */ - var cancelBtn = createButton('Cancel'); - cancelBtn.bind('click', function(event) { - // Close the tab - tab.remove($(this).parent().parent().attr('id')); - }); - setPropsForm.append(cancelBtn); - - // Append to discover tab - tab.add(newTabId, 'Edit', setPropsForm, true); - - // Select new tab - tab.select(newTabId); -} - -/** - * Load copy CD page - */ -function openCopyCdDialog() { - // Create copy Linux form - var dialogId = 'imageCopyCd'; - var copyLinuxForm = $('
                              '); - - // Create info bar - var infoBar = createInfoBar('Copy Linux distributions and service levels from CDs or DVDs to the install directory.'); - copyLinuxForm.append(infoBar); - - // Create Linux ISO input - var iso = $('
                              '); - var isoLabel = $('').css('vertical-align', 'middle'); - var isoInput = $('').css('width', '300px'); - iso.append(isoLabel); - iso.append(isoInput); - copyLinuxForm.append(iso); - - // Create architecture input - copyLinuxForm.append('
                              '); - // Create distribution input - copyLinuxForm.append('
                              '); - - /** - * Browse - */ - var browseBtn = createButton('Browse'); - iso.append(browseBtn); - // Browse server directory and files - browseBtn.serverBrowser({ - onSelect : function(path) { - $('#imageCopyCd #iso').val(path); - }, - onLoad : function() { - return $('#imageCopyCd #iso').val(); - }, - knownExt : [ 'exe', 'js', 'txt' ], - knownPaths : [ { - text : 'Install', - image : 'desktop.png', - path : '/install' - } ], - imageUrl : 'images/serverbrowser/', - systemImageUrl : 'images/serverbrowser/', - handlerUrl : 'lib/getpath.php', - title : 'Browse', - requestMethod : 'POST', - width : '500', - height : '300', - basePath : '/install' // Limit user to only install directory - }); - - // Generate tooltips - copyLinuxForm.find('div input[title],select[title]').tooltip({ - position: "center right", - offset: [-2, 10], - effect: "fade", - opacity: 0.8, - delay: 0, - predelay: 800, - events: { - def: "mouseover,mouseout", - input: "mouseover,mouseout", - widget: "focus mouseover,blur mouseout", - tooltip: "mouseover,mouseout" - }, - - // Change z index to show tooltip in front - onBeforeShow: function() { - this.getTip().css('z-index', $.topZIndex()); - } - }); - - // Open dialog to copy CD - copyLinuxForm.dialog({ - title:'Copy CD', - close: function(){ - $(this).remove(); - }, - modal: true, - width: 600, - buttons: { - "Copy": function() { - // Show loader - $('.ui-dialog #imageCopyCd').append(createLoader('')); - - // Change dialog buttons - $(this).dialog('option', 'buttons', { - 'Close': function() {$(this).dialog("close");} - }); - - // Get image attributes - var iso = $(this).find('input[name="iso"]'); - var arch = $(this).find('input[name="arch"]'); - var distro = $(this).find('input[name="distro"]'); - - // Send ajax request to copy ISO - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'copycds', - tgt : '', - args : '-n;' + distro.val() + ';-a;' + arch.val() + ';' + iso.val(), - msg : dialogId - }, - - success : updateImageDialog - }); - }, - "Cancel": function() { - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Use user input or select to create image - */ -function createImage() { - var osvers = $("#createImageTab #osvers").val(); - var osarch = $("#createImageTab #osarch").val(); - var profile = $("#createImageTab #profile").val(); - var bootInterface = $("#createImageTab #netbootif").val(); - var bootMethod = $("#createImageTab #bootmethod").val(); - - $('#createImageTab .ui-state-error').remove(); - // If there no input for the bootInterface - if (!bootInterface) { - var warnBar = createWarnBar('Please specify the netboot interface'); - $("#createImageTab").prepend(warnBar); - return; - } - - var createImageArgs = "createimage;" + osvers + ";" + osarch + ";" + profile + ";" + bootInterface + ";" + bootMethod + ";"; - - $("#createImageTab :checkbox:checked").each(function() { - createImageArgs += $(this).attr("name") + ","; - }); - - createImageArgs = createImageArgs.substring(0, (createImageArgs.length - 1)); - $.ajax({ - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : createImageArgs, - msg : '' - }, - success : function(data) { - - } - }); +/** + * Global variables + */ +var origAttrs = new Object(); // Original image attributes +var defAttrs; // Definable image attributes +var imgTableId = 'imagesDatatable'; // Images datatable ID +var softwareList = { + "rsct" : ["rsct.core.utils", "rsct.core", "src"], + "pe" : ["IBMJava2-142-ppc64-JRE", "ibm_lapi_ip_rh6p", "ibm_lapi_us_rh6p", "IBM_pe_license", "ibm_pe_rh6p", "ppe_pdb_ppc64_rh600", "sci_ppc_32bit_rh600", "sci_ppc_64bit_rh600", "vac.cmp", + "vac.lib", "vac.lic", "vacpp.cmp", "vacpp.help.pdf", "vacpp.lib", "vacpp.man", "vacpp.rte", "vacpp.rte.lnk", "vacpp.samples", "xlf.cmp", "xlf.help.pdf", "xlf.lib", "xlf.lic", "xlf.man", + "xlf.msg.rte", "xlf.rte", "xlf.rte.lnk", "xlf.samples", "xlmass.lib", "xlsmp.lib", "xlsmp.msg.rte", "xlsmp.rte"], + "gpfs" : ["gpfs.base", "gpfs.gpl", "gpfs.gplbin", "gpfs.msg.en_US"], + "essl" : ["essl.3232.rte", "essl.3264.rte", "essl.6464.rte", "essl.common", "essl.license", "essl.man", "essl.msg", "essl.rte", "ibm-java2", "pessl.common", "pessl.license", "pessl.man", + "pessl.msg", "pessl.rte.ppe"], + "loadl" : ["IBMJava2", "LoadL-full-license-RH6", "LoadL-resmgr-full-RH6", "LoadL-scheduler-full-RH6"], + "ganglia" : ["rrdtool", "ganglia", "ganglia-gmetad", "ganglia-gmond"], + "base" : ["createrepo"] +}; + +/** + * Load images page + */ +function loadImagesPage() { + // Set padding for images page + $('#imagesTab').css('padding', '20px 60px'); + + // Get images within the database + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : '-t;osimage;-l', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadImages(data); + } + }); +} + +/** + * Load images within the database + * + * @param data Data returned from HTTP request + */ +function loadImages(data) { + // Data returned + var rsp = data.rsp; + if (rsp[0].indexOf('Could not find any object definitions') > -1) { + rsp = new Array(); + } + + // Image attributes hash + var attrs = new Object(); + // Image attributes + var headers = new Object(); + + // Clear hash table containing image attributes + origAttrs = ''; + + var image; + var args; + for (var i in rsp) { + // Get the image + var pos = rsp[i].indexOf('Object name:'); + if (pos > -1) { + var temp = rsp[i].split(': '); + image = jQuery.trim(temp[1]); + + // Create a hash for the image attributes + attrs[image] = new Object(); + i++; + } + + // Get key and value + args = rsp[i].split('='); + var key = jQuery.trim(args[0]); + var val = jQuery.trim(args[1]); + + // Create a hash table + attrs[image][key] = val; + headers[key] = 1; + } + + // Save attributes in hash table + origAttrs = attrs; + + // Sort headers + var sorted = new Array(); + for (var key in headers) { + sorted.push(key); + } + sorted.sort(); + + // Add column for check box and image name + sorted.unshift('', 'imagename'); + + // Create a datatable + var dTable = new DataTable(imgTableId); + dTable.init(sorted); + + // Go through each image + for (var img in attrs) { + // Create a row + var row = new Array(); + // Create a check box + var checkBx = ''; + // Push in checkbox and image name + row.push(checkBx, img); + + // Go through each header + for (var i = 2; i < sorted.length; i++) { + // Add the node attributes to the row + var key = sorted[i]; + var val = attrs[img][key]; + if (val) { + row.push(val); + } else { + row.push(''); + } + } + + // Add the row to the table + dTable.add(row); + } + + // Clear the tab before inserting the table + $('#imagesTab').children().remove(); + + // Create info bar for images tab + var info = createInfoBar('Double click on a cell to edit. Click outside the table to save changes. Hit the Escape key to ignore changes.'); + $('#imagesTab').append(info); + + /** + * The following actions are available for images: + * copy Linux distribution and edit image properties + */ + + // Copy CD into install directory + var copyCDLnk = $('Copy CD'); + copyCDLnk.click(function() { + openCopyCdDialog(); + }); + + // Generate stateless or statelite image + var generateLnk = $('Generate image'); + generateLnk.click(function() { + loadCreateImage(); + }); + + // Edit image attributes + var editLnk = $('Edit'); + editLnk.click(function() { + var tgtImages = getNodesChecked(imgTableId).split(','); + if (tgtImages) { + for (var i in tgtImages) { + openEditImagePage(tgtImages[i]); + } + } + }); + + // Add a row + var addLnk = $('Add'); + addLnk.click(function() { + openAddImageDialog(); + }); + + // Remove a row + var removeLnk = $('Remove'); + removeLnk.click(function() { + var images = getNodesChecked(imgTableId); + if (images) { + confirmImageDeleteDialog(images); + } + }); + + // Refresh image table + var refreshLnk = $('Refresh'); + refreshLnk.click(function() { + // Get images within the database + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : '-t;osimage;-l', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadImages(data); + } + }); + }); + + // Insert table + $('#imagesTab').append(dTable.object()); + + // Turn table into a datatable + var myDataTable = $('#' + imgTableId).dataTable({ + 'iDisplayLength': 50, + 'bLengthChange': false, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + + // Set datatable width + $('#' + imgTableId + '_wrapper').css({ + 'width': '880px' + }); + + // Actions + var actionBar = $('
                              ').css("width", "450px"); + var advancedLnk = 'Advanced'; + var advancedMenu = createMenu([copyCDLnk, generateLnk]); + + // Create an action menu + var actionsMenu = createMenu([refreshLnk, addLnk, editLnk, removeLnk, [advancedLnk, advancedMenu]]); + actionsMenu.superfish(); + actionsMenu.css('display', 'inline-block'); + actionBar.append(actionsMenu); + + // Set correct theme for action menu + actionsMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); + $('#' + imgTableId + '_wrapper').prepend(menuDiv); + menuDiv.append(actionBar); + $('#' + imgTableId + '_filter').appendTo(menuDiv); + + /** + * Enable editable columns + */ + + // Do not make 1st or 2nd columns editable + $('#' + imgTableId + ' td:not(td:nth-child(1),td:nth-child(2))').editable( + function(value, settings) { + // Get column index + var colPos = this.cellIndex; + + // Get row index + var dTable = $('#' + imgTableId).dataTable(); + var rowPos = dTable.fnGetPosition(this.parentNode); + + // Update datatable + dTable.fnUpdate(value, rowPos, colPos); + + // Get image name + var image = $(this).parent().find('td:eq(1)').text(); + + // Get table headers + var headers = $('#' + imgTableId).parents('.dataTables_scroll').find('.dataTables_scrollHead thead tr:eq(0) th'); + + // Get attribute name + var attrName = jQuery.trim(headers.eq(colPos).text()); + // Get column value + var value = $(this).text(); + // Build argument + var args = attrName + '=' + value; + + // Send command to change image attributes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chdef', + tgt : '', + args : '-t;osimage;-o;' + image + ';' + args, + msg : 'out=imagesTab;tgt=' + image + }, + + success : function(data) { + data = decodeRsp(data); + showChdefOutput(data); + } + }); + + return value; + }, { + onblur : 'submit', // Clicking outside editable area submits changes + type : 'textarea', // Input type to use + placeholder: ' ', + event : "dblclick", // Double click and edit + height : '30px' // The height of the text area + }); + + // Get definable node attributes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : '-t;osimage;-h', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setImageDefAttrs(data); + } + }); +} + +/** + * Open dialog to confirm deleting image + * + * @param images Comma delimited image names + */ +function confirmImageDeleteDialog(images) { + // Make images list more readable + var dialogId = 'confirmImageRemove'; + var tmp = images.replace(new RegExp(',', 'g'), ', '); + var confirmDialog = $('
                              ' + + '

                              Are you sure you want to remove ' + tmp + '?

                              ' + + '
                              '); + + // Open dialog to confirm delete + confirmDialog.dialog({ + modal: true, + close: function(){ + $(this).remove(); + }, + title: 'Confirm', + width: 500, + buttons: { + "Ok": function(){ + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + // Add image to xCAT + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'rmdef', + tgt : '', + args : '-t;osimage;-o;' + images, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateImageDialog(data); + } + }); + }, + "Cancel": function(){ + $(this).dialog("close"); + } + } + }); +} + +/** + * Open a dialog to add an image + */ +function openAddImageDialog() { + // Create dialog to add image + var dialogId = 'addImage'; + var addImageForm = $('
                              '); + + // Create info bar + var info = createInfoBar('Provide the following attributes for the image. The image name will be generated based on the attributes you will give.'); + + var imageFS = $('
                              '); + var imageLegend = $('Image'); + imageFS.append(imageLegend); + var imageAttr = $('
                              '); + imageFS.append($('
                              ')); + imageFS.append(imageAttr); + + var optionFS = $('
                              '); + var optionLegend = $('Options'); + optionFS.append(optionLegend); + var optionAttr = $('
                              '); + optionFS.append($('
                              ')); + optionFS.append(optionAttr); + + addImageForm.append(info, imageFS, optionFS); + + // Create inputs for image attributes + var imageName = $('
                              '); + var imageType = $('
                              '); + var architecture = $('
                              '); + var osName = $('
                              '); + var osVersion = $('
                              '); + var profile = $('
                              '); + var provisionMethod = $('
                              '); + var provisionSelect = $(''); + provisionMethod.append(provisionSelect); + + // Create inputs for optional attributes + var otherpkgDirectory = $('
                              '); + var otherpkgDirectoryInput = $(''); + otherpkgDirectory.append(otherpkgDirectoryInput); + otherpkgDirectoryInput.serverBrowser({ + onSelect : function(path) { + $('#addImage input[name="otherpkgdir"]').val(path); + }, + onLoad : function() { + return $('#addImage input[name="otherpkgdir"]').val(); + }, + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + var packageDirectory = $('
                              '); + var packageDirectoryInput = $(''); + packageDirectory.append(packageDirectoryInput); + packageDirectoryInput.serverBrowser({ + onSelect : function(path) { + $('#addImage input[name="pkgdir"]').val(path); + }, + onLoad : function() { + return $('#addImage input[name="pkgdir"]').val(); + }, + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + var packageList = $('
                              '); + var packageListInput = $(''); + packageList.append(packageListInput); + packageListInput.serverBrowser({ + onSelect : function(path) { + $('#addImage input[name="pkglist"]').val(path); + }, + onLoad : function() { + return $('#addImage input[name="pkglist"]').val(); + }, + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + var template = $('
                              '); + var templateInput = $(''); + template.append(templateInput); + templateInput.serverBrowser({ + onSelect : function(path) { + $('#addImage input[name="template"]').val(path); + }, + onLoad : function() { + return $('#addImage input[name="template"]').val(); + }, + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + + imageAttr.append(imageName, imageType, architecture, osName, osVersion, profile, provisionMethod); + optionAttr.append(otherpkgDirectory, packageDirectory, packageList, template); + + // Generate tooltips + addImageForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to add image + addImageForm.dialog({ + title:'Add image', + modal: true, + close: function(){ + $(this).remove(); + }, + beight: 400, + width: 600, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + // Get image attributes + var imageType = $(this).find('input[name="imagetype"]'); + var architecture = $(this).find('input[name="osarch"]'); + var osName = $(this).find('input[name="osname"]'); + var osVersion = $(this).find('input[name="osvers"]'); + var profile = $(this).find('input[name="profile"]'); + var provisionMethod = $(this).find('select[name="provmethod"]'); + + // Get optional image attributes + var otherpkgDirectory = $(this).find('input[name="otherpkgdir"]'); + var pkgDirectory = $(this).find('input[name="pkgdir"]'); + var pkgList = $(this).find('input[name="pkglist"]'); + var template = $(this).find('input[name="template"]'); + + // Check that image attributes are provided before continuing + var ready = 1; + var inputs = new Array(imageType, architecture, osName, osVersion, profile, provisionMethod); + for (var i in inputs) { + if (!inputs[i].val()) { + inputs[i].css('border-color', 'red'); + ready = 0; + } else + inputs[i].css('border-color', ''); + } + + // If inputs are not complete, show warning message + if (!ready) { + var warn = createWarnBar('Please provide a value for each missing field.'); + warn.prependTo($(this)); + } else { + // Override image name + $(this).find('input[name="imagename"]').val(osVersion.val() + '-' + architecture.val() + '-' + provisionMethod.val() + '-' + profile.val()); + var imageName = $(this).find('input[name="imagename"]'); + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + // Create arguments to send via AJAX + var args = '-t;osimage;-o;' + imageName.val() + ';' + + 'imagetype=' + imageType.val() + ';' + + 'osarch=' + architecture.val() + ';' + + 'osname=' + osName.val() + ';' + + 'osvers=' + osVersion.val() + ';' + + 'profile=' + profile.val() + ';' + + 'provmethod=' + provisionMethod.val(); + + // Get optional attributes + if (otherpkgDirectory.val()) + args += ';otherpkgdir=' + otherpkgDirectory.val(); + if (pkgDirectory.val()) + args += ';pkgdir=' + pkgDirectory.val(); + if (pkgList.val()) + args += ';pkglist=' + pkgList.val(); + if (template.val()) + args += ';template=' + template.val(); + + // Add image to xCAT + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chdef', + tgt : '', + args : args, + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateImageDialog(data); + } + }); + } + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Update image dialog + * + * @param data HTTP request data + */ +function updateImageDialog(data) { + var dialogId = data.msg; + var infoMsg; + + // Delete loader if one does exist + $('.ui-dialog #' + dialogId + ' img[src="images/loader.gif"]').remove(); + + // Create info message + if (jQuery.isArray(data.rsp)) { + infoMsg = ''; + + // If the data returned is more than 10 lines, get only the last line + var i, start; + if (data.rsp.length > 10) + start = data.rsp.length - 1; + else + start = 0; + + for (i = start; i < data.rsp.length; i++) + infoMsg += data.rsp[i] + '
                              '; + } else { + infoMsg = data.rsp; + } + + // Create info bar with close button + var infoBar = $('
                              ').css('margin', '5px 0px'); + var icon = $('').css({ + 'display': 'inline-block', + 'margin': '10px 5px' + }); + + // Create close button to close info bar + var close = $('').css({ + 'display': 'inline-block', + 'float': 'right' + }).click(function() { + $(this).parent().remove(); + }); + + var msg = $('

                              ' + infoMsg + '

                              ').css({ + 'display': 'inline-block', + 'width': '90%' + }); + + infoBar.append(icon, msg, close); + infoBar.prependTo($('.ui-dialog #' + dialogId)); +} + +/** + * Set definable image attributes + * + * @param data Data returned from HTTP request + */ +function setImageDefAttrs(data) { + // Clear hash table containing definable image attributes + defAttrs = new Array(); + + // Get definable attributes + var attrs = data.rsp[2].split(/\n/); + + // Go through each line + var attr, key, descr; + for (var i in attrs) { + attr = attrs[i]; + + // If the line is not empty + if (attr) { + // If the line has the attribute name + if (attr.indexOf(':') && attr.indexOf(' ')) { + // Get attribute name and description + key = jQuery.trim(attr.substring(0, attr.indexOf(':'))); + descr = jQuery.trim(attr.substring(attr.indexOf(':') + 1)); + descr = descr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']'); + + // Set hash table where key = attribute name and value = description + defAttrs[key] = descr; + } else { + // Append description to hash table + defAttrs[key] = defAttrs[key] + '\n' + attr.replace(new RegExp('<', 'g'), '[').replace(new RegExp('>', 'g'), ']'); + } + } // End of if + } // End of for +} + +/** + * Load create image page + */ +function loadCreateImage() { + // Get nodes tab + var tab = getProvisionTab(); + var tabId = 'createImageTab'; + + // Generate new tab ID + if ($('#' + tabId).size()) { + tab.select(tabId); + return; + } + + var imageOsVers = $.cookie("xcat_osvers").split(","); + var imageArch = $.cookie("xcat_osarchs").split(","); + var profiles = $.cookie("xcat_profiles").split(","); + + var createImgForm = $('
                              '); + var createImgFS = $('
                              ').append('Create Image'); + createImgForm.append(createImgFS); + + // Show info bar + var infoBar = createInfoBar('Specify the parameters for the image (stateless or statelite) you want to create, then click Create.'); + createImgFS.append(infoBar); + + // Drop down for OS versions + var osVerSelect = $(''); + for (var i in imageOsVers) + osVerSelect.append(''); + createImgFS.append($('
                              ').append(osVerSelect)); + + // Drop down for OS architectures + var imgSelect = $(''); + for (var i in imageArch) + imgSelect.append(''); + createImgFS.append($('
                              ').append(imgSelect)); + + // Netboot interface input + createImgFS.append($('
                              ')); + + // Profile selector + var profileSelect = $('' + + '' + + '' + + '
                              ')); + + // Create HPC software stack fieldset + createHpcFS(createImgForm); + + // The button used to create images is created here + var createImageBtn = createButton("Create"); + createImageBtn.bind('click', function(event) { + createImage(); + }); + + createImgForm.append(createImageBtn); + + // Add tab + tab.add(tabId, 'Create', createImgForm, true); + tab.select(tabId); + + // Check the selected OS version and OS arch for HPC stack + // If they are valid, show the HCP stack fieldset + hpcShow(); +} + +/** + * Create HPC fieldset + * + * @param container The container to hold the HPC fieldset + */ +function createHpcFS(container) { + var hpcFieldset = $('
                              '); + hpcFieldset.append('HPC Software Stack'); + + var str = 'Before selecting the software, you should have the following already completed on your xCAT cluster:

                              ' + + '1. If you are using the xCAT hierarchy, your service nodes are installed and running.
                              ' + + '2. Your compute nodes are defined in xCAT, and you have verified your hardware control capabilities, ' + + 'gathered MAC addresses, and done all the other necessary preparations for a diskless install.
                              ' + + '3. You should have a diskless image created with the base OS installed and verified it on at least one test node.
                              ' + + '4. You should install the software on the management node and copy all correponding packages into the location "/install/custom/otherpkgs/" based on ' + + 'these documents.
                              '; + hpcFieldset.append(createInfoBar(str)); + + // Advanced software + str = '
                              • GPFS
                              • ' + + '
                              • RSCT
                              • ' + + '
                              • PE
                              • ' + + '
                              • ESSl & PESSL
                              • ' + + '
                              ' + + '
                              • Ganglia
                              • ' + + '
                              '; + hpcFieldset.append(str); + + container.append($('
                              ').append(hpcFieldset)); +} + +/** + * Check the dependance for ESSL and start the software check for ESSL + * + * @param softwareObject The checkbox object of ESSL + */ +function esslCheck(softwareObject) { + var softwareName = softwareObject.name; + if (!$('#createImageTab input[name=pe]').attr('checked')) { + var warnBar = createWarnBar('You must first select the PE'); + $(':checkbox[name=essl]').attr("checked", false); + + // Clear existing warnings and append new warning + $('#hpcsoft .ui-state-error').remove(); + $('#hpcsoft').prepend(warnBar); + + return; + } else { + softwareCheck(softwareObject); + } +} + +/** + * Check the parameters for the HPC software + * + * @param softwareObject Checkbox object of the HPC software + * @return True if the checkbox is checked, false otherwise + */ +function softwareCheck(softwareObject) { + var softwareName = softwareObject.name; + $('#createImageTab #' + softwareName + 'li .ui-state-error').remove(); + $('#createImageTab #' + softwareName + 'li').append(createLoader()); + var cmdString = genRpmCmd(softwareName); + $.ajax( { + url : 'lib/systemcmd.php', + dataType : 'json', + data : { + cmd : cmdString, + msg : softwareName + }, + success : function(data) { + if (rpmCheck(data.rsp, data.msg)) { + genLsCmd(data.msg); + $.ajax( { + url : 'lib/systemcmd.php', + dataType : 'json', + data : { + cmd : genLsCmd(data.msg), + msg : data.msg + }, + success : function(data) { + data = decodeRsp(data); + rpmCopyCheck(data); + } + }); + } + } + }); +} + +/** + * Check if the RPMs are copied to the special location + * + * @param data Data returned from HTTP request + */ +function rpmCopyCheck(data) { + // Remove the loading image + var errorStr = ''; + var softwareName = data.msg; + + // Check the return information + var reg = /.+:(.+): No such.*/; + var resultArray = data.rsp.split("\n"); + for ( var i in resultArray) { + var temp = reg.exec(resultArray[i]); + if (temp) { + // Find out the path and RPM name + var pos = temp[1].lastIndexOf('/'); + var path = temp[1].substring(0, pos); + var rpmName = temp[1].substring(pos + 1).replace('*', ''); + errorStr += 'copy ' + rpmName + ' to ' + path + '
                              '; + } + } + $('#createImageTab #' + softwareName + 'li').find('img').remove(); + + // No error, show the check image + if (!errorStr) { + var infoPart = '
                              '; + $('#createImageTab #' + softwareName + 'li').append(infoPart); + } else { + // Show the error message + errorStr = 'To install the RSCT on your compute node. You should:
                              ' + errorStr + '
                              '; + var warnBar = createWarnBar(errorStr); + $(':checkbox[name=' + softwareName + ']').attr("checked", false); + + // Clear existing warnings and append new warning + $('#hpcsoft .ui-state-error').remove(); + $('#hpcsoft').prepend(warnBar); + } +} + +/** + * Generate the RPM command for rpmcheck + * + * @param softwareName The name of the software + * @return The RPM command + */ +function genRpmCmd(softwareName) { + var cmdString; + cmdString = 'rpm -q '; + for (var i in softwareList[softwareName]) { + cmdString += softwareList[softwareName][i] + ' '; + } + + for (var i in softwareList['base']) { + cmdString += softwareList['base'][i] + ' '; + } + + return cmdString; +} + +/** + * Check if the RPMs for the HPC software are copied to the special location + * + * @param softwareName The name of the software + */ +function genLsCmd(softwareName) { + var osvers = $('#createImageTab #osvers').val(); + var osarch = $('#createImageTab #osarch').val(); + var path = '/install/post/otherpkgs/' + osvers + '/' + osarch + '/' + softwareName; + var checkCmd = 'ls '; + + for (var i in softwareList[softwareName]) { + checkCmd += path + '/' + softwareList[softwareName][i] + '*.rpm '; + } + checkCmd += '2>&1'; + + return checkCmd; +} + +/** + * Check if all RPMs are installed + * + * @param checkInfo 'rpm -q' output + * @return True if all RPMs are installed, false otherwise + */ +function rpmCheck(checkInfo, name) { + var errorStr = ''; + + var checkArray = checkInfo.split('\n'); + for (var i in checkArray) { + if (checkArray[i].indexOf('not install') != -1) { + errorStr += checkArray[i] + '
                              '; + } + } + + if (!errorStr) { + return true; + } + + errorStr = errorStr.substr(0, errorStr.length - 1); + $(':checkbox[name=' + name + ']').attr('checked', false); + + // Add the error + var warnBar = createWarnBar(errorStr); + $('#createImageTab #' + name + 'li').find('img').remove(); + + // Clear existing warnings and append new warning + $('#hpcsoft .ui-state-error').remove(); + $('#hpcsoft').prepend(warnBar); + + return; +} + +/** + * Check the option and decide whether to show the hpcsoft or not + */ +function hpcShow() { + // The current UI only supports RHELS 6 + // If you want to support all, delete the subcheck + if ($('#createImageTab #osvers').attr('value') != "rhels6" || $('#createImageTab #osarch').attr('value') != "ppc64" || $('#createImageTab #profile').attr('value') != "compute") { + $('#createImageTab #partlysupport').hide(); + } else { + $('#createImageTab #partlysupport').show(); + } +} + +/** + * Load set image properties page + * + * @param tgtImage Target image to set properties + */ +function openEditImagePage(tgtImage) { + // Get nodes tab + var tab = getProvisionTab(); + + // Generate new tab ID + var inst = 0; + var newTabId = 'editImageTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = 'editImageTab' + inst; + } + + // Open new tab + // Create set properties form + var setPropsForm = $('
                              '); + + // Create info bar + var infoBar = createInfoBar('Choose the properties you wish to change on the node. When you are finished, click Save.'); + setPropsForm.append(infoBar); + + // Create an input for each definable attribute + var div, label, input, value; + var attrIndex = 0; + // Set node attribute + origAttrs[tgtImage]['imagename'] = tgtImage; + for (var key in defAttrs) { + // If an attribute value exists + if (origAttrs[tgtImage][key]) { + // Set the value + value = origAttrs[tgtImage][key]; + } else { + value = ''; + } + + // Create label and input for attribute + div = $('
                              ').css('display', 'inline'); + label = $('').css('vertical-align', 'middle'); + input = $('').css({ + 'margin-top': '5px', + 'float': 'none', + 'width': 'inherit' + }); + + // There is an element called groups that will override the defaults for the groups attribute. + // Hence, the input must have use CSS to override the float and width. + + // Split attributes into 2 per row + if (attrIndex > 0 && !(attrIndex % 2)) { + div.css('display', 'inline-block'); + } + + attrIndex++; + + // Create server browser + switch (key) { + case 'pkgdir': + input.serverBrowser({ + onSelect : function(path) { + $('#pkgdir').val(path); + }, + onLoad : function() { + return $('#pkgdir').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + break; + case 'otherpkgdir': + input.serverBrowser({ + onSelect : function(path) { + $('#otherpkgdir').val(path); + }, + onLoad : function() { + return $('#otherpkgdir').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + break; + case 'pkglist': + input.serverBrowser({ + onSelect : function(path) { + $('#pkglist').val(path); + }, + onLoad : function() { + return $('#pkglist').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/opt/xcat/share' // Limit user to only install directory + }); + break; + case 'otherpkglist': + input.serverBrowser({ + onSelect : function(path) { + $('#otherpkglist').val(path); + }, + onLoad : function() { + return $('#otherpkglist').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + break; + case 'template': + input.serverBrowser({ + onSelect : function(path) { + $('#template').val(path); + }, + onLoad : function() { + return $('#template').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [{ + text : 'Install', + image : 'desktop.png', + path : '/install' + }], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/opt/xcat/share' // Limit user to only install directory + }); + break; + default: + // Do nothing + } + + // Change border to blue onchange + input.bind('change', function(event) { + $(this).css('border-color', 'blue'); + }); + + div.append(label, input); + setPropsForm.append(div); + } + + // Change style for last division + div.css({ + 'display': 'block', + 'margin': '0px 0px 10px 0px' + }); + + // Generate tooltips + setPropsForm.find('div input[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 500, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + } + }); + + /** + * Save + */ + var saveBtn = createButton('Save'); + saveBtn.bind('click', function(event) { + // Get all inputs + var inputs = $('#' + newTabId + ' input'); + + // Go through each input + var args = ''; + var attrName, attrVal; + inputs.each(function(){ + // If the border color is blue + if ($(this).css('border-left-color') == 'rgb(0, 0, 255)') { + // Change border color back to normal + $(this).css('border-color', ''); + + // Get attribute name and value + attrName = $(this).parent().find('label').text().replace(':', ''); + attrVal = $(this).val(); + + // Build argument string + if (args) { + // Handle subsequent arguments + args += ';' + attrName + '=' + attrVal; + } else { + // Handle the 1st argument + args += attrName + '=' + attrVal; + } + } + }); + + // Send command to change image attributes + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'chdef', + tgt : '', + args : '-t;osimage;-o;' + tgtImage + ';' + args, + msg : 'out=' + newTabId + ';tgt=' + tgtImage + }, + + success : function(data) { + data = decodeRsp(data); + showChdefOutput(data); + } + }); + }); + setPropsForm.append(saveBtn); + + /** + * Cancel + */ + var cancelBtn = createButton('Cancel'); + cancelBtn.bind('click', function(event) { + // Close the tab + tab.remove($(this).parent().parent().attr('id')); + }); + setPropsForm.append(cancelBtn); + + // Append to discover tab + tab.add(newTabId, 'Edit', setPropsForm, true); + + // Select new tab + tab.select(newTabId); +} + +/** + * Load copy CD page + */ +function openCopyCdDialog() { + // Create copy Linux form + var dialogId = 'imageCopyCd'; + var copyLinuxForm = $('
                              '); + + // Create info bar + var infoBar = createInfoBar('Copy Linux distributions and service levels from CDs or DVDs to the install directory.'); + copyLinuxForm.append(infoBar); + + // Create Linux ISO input + var iso = $('
                              '); + var isoLabel = $('').css('vertical-align', 'middle'); + var isoInput = $('').css('width', '300px'); + iso.append(isoLabel); + iso.append(isoInput); + copyLinuxForm.append(iso); + + // Create architecture input + copyLinuxForm.append('
                              '); + // Create distribution input + copyLinuxForm.append('
                              '); + + /** + * Browse + */ + var browseBtn = createButton('Browse'); + iso.append(browseBtn); + // Browse server directory and files + browseBtn.serverBrowser({ + onSelect : function(path) { + $('#imageCopyCd #iso').val(path); + }, + onLoad : function() { + return $('#imageCopyCd #iso').val(); + }, + knownExt : [ 'exe', 'js', 'txt' ], + knownPaths : [ { + text : 'Install', + image : 'desktop.png', + path : '/install' + } ], + imageUrl : 'images/serverbrowser/', + systemImageUrl : 'images/serverbrowser/', + handlerUrl : 'lib/getpath.php', + title : 'Browse', + requestMethod : 'POST', + width : '500', + height : '300', + basePath : '/install' // Limit user to only install directory + }); + + // Generate tooltips + copyLinuxForm.find('div input[title],select[title]').tooltip({ + position: "center right", + offset: [-2, 10], + effect: "fade", + opacity: 0.8, + delay: 0, + predelay: 800, + events: { + def: "mouseover,mouseout", + input: "mouseover,mouseout", + widget: "focus mouseover,blur mouseout", + tooltip: "mouseover,mouseout" + }, + + // Change z index to show tooltip in front + onBeforeShow: function() { + this.getTip().css('z-index', $.topZIndex()); + } + }); + + // Open dialog to copy CD + copyLinuxForm.dialog({ + title:'Copy CD', + close: function(){ + $(this).remove(); + }, + modal: true, + width: 600, + buttons: { + "Copy": function() { + // Show loader + $('.ui-dialog #imageCopyCd').append(createLoader('')); + + // Change dialog buttons + $(this).dialog('option', 'buttons', { + 'Close': function() {$(this).dialog("close");} + }); + + // Get image attributes + var iso = $(this).find('input[name="iso"]'); + var arch = $(this).find('input[name="arch"]'); + var distro = $(this).find('input[name="distro"]'); + + // Send ajax request to copy ISO + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'copycds', + tgt : '', + args : '-n;' + distro.val() + ';-a;' + arch.val() + ';' + iso.val(), + msg : dialogId + }, + + success : function(data) { + data = decodeRsp(data); + updateImageDialog(data); + } + }); + }, + "Cancel": function() { + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Use user input or select to create image + */ +function createImage() { + var osvers = $("#createImageTab #osvers").val(); + var osarch = $("#createImageTab #osarch").val(); + var profile = $("#createImageTab #profile").val(); + var bootInterface = $("#createImageTab #netbootif").val(); + var bootMethod = $("#createImageTab #bootmethod").val(); + + $('#createImageTab .ui-state-error').remove(); + // If there no input for the bootInterface + if (!bootInterface) { + var warnBar = createWarnBar('Please specify the netboot interface'); + $("#createImageTab").prepend(warnBar); + return; + } + + var createImageArgs = "createimage;" + osvers + ";" + osarch + ";" + profile + ";" + bootInterface + ";" + bootMethod + ";"; + + $("#createImageTab :checkbox:checked").each(function() { + createImageArgs += $(this).attr("name") + ","; + }); + + createImageArgs = createImageArgs.substring(0, (createImageArgs.length - 1)); + $.ajax({ + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : createImageArgs, + msg : '' + }, + success : function(data) { + data = decodeRsp(data); + } + }); } \ No newline at end of file diff --git a/xCAT-UI/js/provision/provision.js b/xCAT-UI/js/provision/provision.js index 00a059080..f3a394df5 100644 --- a/xCAT-UI/js/provision/provision.js +++ b/xCAT-UI/js/provision/provision.js @@ -1,252 +1,258 @@ -/** - * Global variables - */ -var provisionTabs; // Provision tabs - -/** - * Set the provision tab - * - * @param obj Tab object - */ -function setProvisionTab(obj) { - provisionTabs = obj; -} - -/** - * Get the provision tab - * - * @param Nothing - * @return Tab object - */ -function getProvisionTab() { - return provisionTabs; -} - -/** - * Load provision page - */ -function loadProvisionPage() { - // If the page is loaded - if ($('#content').children().length) { - // Do not load again - return; - } - - // Get OS image names - if (!$.cookie('xcat_imagenames')){ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : 'osimage', - msg : '' - }, - - success : setOSImageCookies - }); - } - - // Get groups - if (!$.cookie('xcat_groups')){ - $.ajax( { - url : 'lib/cmd.php', - dataType : 'json', - data : { - cmd : 'extnoderange', - tgt : '/.*', - args : 'subgroups', - msg : '' - }, - - success : setGroupsCookies - }); - } - - // Create info bar - var infoBar = createInfoBar('Select a platform to provision or re-provision a node on, then click Ok.'); - - // Create provision page - var provPg = $('
                              '); - provPg.append(infoBar); - - // Create provision tab - var tab = new Tab('provisionPageTabs'); - setProvisionTab(tab); - tab.init(); - $('#content').append(tab.object()); - - // Create radio buttons for platforms - var hwList = $('
                                Platforms available:
                              '); - var esx = $('
                            • ESX
                            • '); - var kvm = $('
                            • KVM
                            • '); - var zvm = $('
                            • z\/VM
                            • '); - var ipmi = $('
                            • iDataPlex
                            • '); - var blade = $('
                            • BladeCenter
                            • '); - var hmc = $('
                            • System p
                            • '); - - hwList.append(esx); - hwList.append(kvm); - hwList.append(zvm); - hwList.append(blade); - hwList.append(ipmi); - hwList.append(hmc); - provPg.append(hwList); - - /** - * Ok - */ - var okBtn = createButton('Ok'); - okBtn.bind('click', function(event) { - // Get hardware that was selected - var hw = $(this).parent().find('input[name="hw"]:checked').val(); - - var inst = 0; - var newTabId = hw + 'ProvisionTab' + inst; - while ($('#' + newTabId).length) { - // If one already exists, generate another one - inst = inst + 1; - newTabId = hw + 'ProvisionTab' + inst; - } - - // Create an instance of the plugin - var title = ''; - var plugin; - switch (hw) { - case "kvm": - plugin = new kvmPlugin(); - title = 'KVM'; - break; - case "esx": - plugin = new esxPlugin(); - title = 'ESX'; - break; - case "blade": - plugin = new bladePlugin(); - title = 'BladeCenter'; - break; - case "hmc": - plugin = new hmcPlugin(); - title = 'System p'; - break; - case "ipmi": - plugin = new ipmiPlugin(); - title = 'iDataPlex'; - break; - case "zvm": - plugin = new zvmPlugin(); - title = 'z/VM'; - break; - } - - // Select tab - tab.add(newTabId, title, '', true); - tab.select(newTabId); - plugin.loadProvisionPage(newTabId); - }); - provPg.append(okBtn); - - // Create resources tab - var resrcPg = $('
                              '); - - // Create info bar - var resrcInfoBar = createInfoBar('Select a platform to view its current resources.'); - resrcPg.append(resrcInfoBar); - - // Create radio buttons for platforms - var rsrcHwList = $('
                                Platforms available:
                              '); - esx = $('
                            • ESX
                            • '); - kvm = $('
                            • KVM
                            • '); - zvm = $('
                            • z\/VM
                            • '); - ipmi = $('
                            • iDataPlex
                            • '); - blade = $('
                            • BladeCenter
                            • '); - hmc = $('
                            • System p
                            • '); - - rsrcHwList.append(esx); - rsrcHwList.append(kvm); - rsrcHwList.append(zvm); - rsrcHwList.append(blade); - rsrcHwList.append(ipmi); - rsrcHwList.append(hmc); - - resrcPg.append(rsrcHwList); - - var okBtn = createButton('Ok'); - okBtn.bind('click', function(event) { - // Get hardware that was selected - var hw = $(this).parent().find('input[name="rsrcHw"]:checked').val(); - - // Generate new tab ID - var newTabId = hw + 'ResourceTab'; - if (!$('#' + newTabId).length) { - // Create loader - var loader = $('
                              ').append(createLoader(hw + 'ResourceLoader')); - - // Create an instance of the plugin - var plugin = null; - var displayName = ""; - switch (hw) { - case "kvm": - plugin = new kvmPlugin(); - displayName = "KVM"; - break; - case "esx": - plugin = new esxPlugin(); - displayName = "ESX"; - break; - case "blade": - plugin = new bladePlugin(); - displayName = "BladeCenter"; - break; - case "hmc": - plugin = new hmcPlugin(); - displayName = "System p"; - break; - case "ipmi": - plugin = new ipmiPlugin(); - displayName = "iDataPlex"; - break; - case "zvm": - plugin = new zvmPlugin(); - displayName = "z\/VM"; - break; - } - - // Add resource tab and load resources - tab.add(newTabId, displayName, loader, true); - plugin.loadResources(); - } - - // Select tab - tab.select(newTabId); - }); - - resrcPg.append(okBtn); - - // Add provision tab - tab.add('provisionTab', 'Provision', provPg, false); - // Add image tab - tab.add('imagesTab', 'Images', '', false); - // Add resource tab - tab.add('resourceTab', 'Resources', resrcPg, false); - - // Load tabs onselect - $('#provisionPageTabs').bind('tabsselect', function(event, ui){ - // Load image page - if (!$('#imagesTab').children().length && ui.index == 1) { - $('#imagesTab').append($('
                              ').append(createLoader(''))); - loadImagesPage(); - } - }); - - // Open the quick provision tab - if (window.location.search) { - tab.add('quickProvisionTab', 'Quick Provision', '', true); - tab.select('quickProvisionTab'); - - var provForm = $('
                              '); - $('#quickProvisionTab').append(provForm); - appendProvisionSection('quick', provForm); - } +/** + * Global variables + */ +var provisionTabs; // Provision tabs + +/** + * Set the provision tab + * + * @param obj Tab object + */ +function setProvisionTab(obj) { + provisionTabs = obj; +} + +/** + * Get the provision tab + * + * @param Nothing + * @return Tab object + */ +function getProvisionTab() { + return provisionTabs; +} + +/** + * Load provision page + */ +function loadProvisionPage() { + // If the page is loaded + if ($('#content').children().length) { + // Do not load again + return; + } + + // Get OS image names + if (!$.cookie('xcat_imagenames')){ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'osimage', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setOSImageCookies(data); + } + }); + } + + // Get groups + if (!$.cookie('xcat_groups')){ + $.ajax( { + url : 'lib/cmd.php', + dataType : 'json', + data : { + cmd : 'extnoderange', + tgt : '/.*', + args : 'subgroups', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setGroupsCookies(data); + } + }); + } + + // Create info bar + var infoBar = createInfoBar('Select a platform to provision or re-provision a node on, then click Ok.'); + + // Create provision page + var provPg = $('
                              '); + provPg.append(infoBar); + + // Create provision tab + var tab = new Tab('provisionPageTabs'); + setProvisionTab(tab); + tab.init(); + $('#content').append(tab.object()); + + // Create radio buttons for platforms + var hwList = $('
                                Platforms available:
                              '); + var esx = $('
                            • ESX
                            • '); + var kvm = $('
                            • KVM
                            • '); + var zvm = $('
                            • z\/VM
                            • '); + var ipmi = $('
                            • iDataPlex
                            • '); + var blade = $('
                            • BladeCenter
                            • '); + var hmc = $('
                            • System p
                            • '); + + hwList.append(esx); + hwList.append(kvm); + hwList.append(zvm); + hwList.append(blade); + hwList.append(ipmi); + hwList.append(hmc); + provPg.append(hwList); + + /** + * Ok + */ + var okBtn = createButton('Ok'); + okBtn.bind('click', function(event) { + // Get hardware that was selected + var hw = $(this).parent().find('input[name="hw"]:checked').val(); + + var inst = 0; + var newTabId = hw + 'ProvisionTab' + inst; + while ($('#' + newTabId).length) { + // If one already exists, generate another one + inst = inst + 1; + newTabId = hw + 'ProvisionTab' + inst; + } + + // Create an instance of the plugin + var title = ''; + var plugin; + switch (hw) { + case "kvm": + plugin = new kvmPlugin(); + title = 'KVM'; + break; + case "esx": + plugin = new esxPlugin(); + title = 'ESX'; + break; + case "blade": + plugin = new bladePlugin(); + title = 'BladeCenter'; + break; + case "hmc": + plugin = new hmcPlugin(); + title = 'System p'; + break; + case "ipmi": + plugin = new ipmiPlugin(); + title = 'iDataPlex'; + break; + case "zvm": + plugin = new zvmPlugin(); + title = 'z/VM'; + break; + } + + // Select tab + tab.add(newTabId, title, '', true); + tab.select(newTabId); + plugin.loadProvisionPage(newTabId); + }); + provPg.append(okBtn); + + // Create resources tab + var resrcPg = $('
                              '); + + // Create info bar + var resrcInfoBar = createInfoBar('Select a platform to view its current resources.'); + resrcPg.append(resrcInfoBar); + + // Create radio buttons for platforms + var rsrcHwList = $('
                                Platforms available:
                              '); + esx = $('
                            • ESX
                            • '); + kvm = $('
                            • KVM
                            • '); + zvm = $('
                            • z\/VM
                            • '); + ipmi = $('
                            • iDataPlex
                            • '); + blade = $('
                            • BladeCenter
                            • '); + hmc = $('
                            • System p
                            • '); + + rsrcHwList.append(esx); + rsrcHwList.append(kvm); + rsrcHwList.append(zvm); + rsrcHwList.append(blade); + rsrcHwList.append(ipmi); + rsrcHwList.append(hmc); + + resrcPg.append(rsrcHwList); + + var okBtn = createButton('Ok'); + okBtn.bind('click', function(event) { + // Get hardware that was selected + var hw = $(this).parent().find('input[name="rsrcHw"]:checked').val(); + + // Generate new tab ID + var newTabId = hw + 'ResourceTab'; + if (!$('#' + newTabId).length) { + // Create loader + var loader = $('
                              ').append(createLoader(hw + 'ResourceLoader')); + + // Create an instance of the plugin + var plugin = null; + var displayName = ""; + switch (hw) { + case "kvm": + plugin = new kvmPlugin(); + displayName = "KVM"; + break; + case "esx": + plugin = new esxPlugin(); + displayName = "ESX"; + break; + case "blade": + plugin = new bladePlugin(); + displayName = "BladeCenter"; + break; + case "hmc": + plugin = new hmcPlugin(); + displayName = "System p"; + break; + case "ipmi": + plugin = new ipmiPlugin(); + displayName = "iDataPlex"; + break; + case "zvm": + plugin = new zvmPlugin(); + displayName = "z\/VM"; + break; + } + + // Add resource tab and load resources + tab.add(newTabId, displayName, loader, true); + plugin.loadResources(); + } + + // Select tab + tab.select(newTabId); + }); + + resrcPg.append(okBtn); + + // Add provision tab + tab.add('provisionTab', 'Provision', provPg, false); + // Add image tab + tab.add('imagesTab', 'Images', '', false); + // Add resource tab + tab.add('resourceTab', 'Resources', resrcPg, false); + + // Load tabs onselect + $('#provisionPageTabs').bind('tabsselect', function(event, ui){ + // Load image page + if (!$('#imagesTab').children().length && ui.index == 1) { + $('#imagesTab').append($('
                              ').append(createLoader(''))); + loadImagesPage(); + } + }); + + // Open the quick provision tab + if (window.location.search) { + tab.add('quickProvisionTab', 'Quick Provision', '', true); + tab.select('quickProvisionTab'); + + var provForm = $('
                              '); + $('#quickProvisionTab').append(provForm); + appendProvisionSection('quick', provForm); + } } \ No newline at end of file diff --git a/xCAT-UI/js/service/service.js b/xCAT-UI/js/service/service.js index 3d49b98d9..0ffcaf7d4 100644 --- a/xCAT-UI/js/service/service.js +++ b/xCAT-UI/js/service/service.js @@ -1,2153 +1,2192 @@ -/** - * Global variables - */ -var serviceTabs; -var nodeName; -var nodePath; -var nodeStatus; -var gangliaTimer; - -/** - * Initialize service page - */ -function initServicePage() { - // Load theme - var theme = $.cookie('xcat_theme'); - if (theme) { - switch (theme) { - case 'cupertino': - includeCss("css/themes/jquery-ui-cupertino.css"); - break; - case 'dark_hive': - includeCss("css/themes/jquery-ui-dark_hive.css"); - break; - case 'redmond': - includeCss("css/themes/jquery-ui-redmond.css"); - break; - case 'start': - includeCss("css/themes/jquery-ui-start.css"); - break; - case 'sunny': - includeCss("css/themes/jquery-ui-sunny.css"); - break; - case 'ui_dark': - includeCss("css/themes/jquery-ui-ui_darkness.css"); - break; - default: - includeCss("css/themes/jquery-ui-start.css"); - } - } else { - includeCss("css/themes/jquery-ui-start.css"); - } - - // Load jQuery stylesheets - includeCss("css/jquery.dataTables.css"); - includeCss("css/superfish.css"); - includeCss("css/jstree.css"); - includeCss("css/jquery.jqplot.css"); - - // Load custom stylesheet - includeCss("css/style.css"); - - // 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"); - - // Custom plugins - includeJs("js/custom/esx.js"); - includeJs("js/custom/kvm.js"); - includeJs("js/custom/zvm.js"); - - // Enable settings link - $('#xcat_settings').click(function() { - openSettings(); - }); - - // Show service page - $("#content").children().remove(); - includeJs("js/service/utils.js"); - loadServicePage(); - - // Initialize tab index history - $.cookie('xcat_tabindex_history', '0,0', { path: '/xcat', secure:true }); -} - -/** - * 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); - - // 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); - setMaxVM(); - getUserNodesDef(); - getNodesCurrentLoad(); - loadManagePage(manageTabId); - } - }); - - // Get OS image names - $.ajax({ - url : 'lib/srv_cmd.php', - dataType : 'json', - async : true, - data : { - cmd : 'tabdump', - tgt : '', - args : 'osimage', - msg : '' - }, - - success : function(data) { - setOSImageCookies(data); - } - }); - - // Get contents of hosts table - $.ajax({ - url : 'lib/srv_cmd.php', - dataType : 'json', - async : true, - data : { - cmd : 'tabdump', - tgt : '', - args : 'hosts', - msg : '' - }, - - success : function(data) { - setGroupCookies(data); - } - }); - - var provTabId = 'provisionTab'; - serviceTabs.add(provTabId, 'Provision', '', false); - loadServiceProvisionPage(provTabId); - - serviceTabs.select(manageTabId); -} - -/** - * Load the service portal's provision page - * - * @param tabId Tab ID where page will reside - */ -function loadServiceProvisionPage(tabId) { - // Create info bar - var infoBar = createInfoBar('Select a platform to provision a node on, then click Ok.'); - - // Create provision page - var provPg = $('
                              '); - $('#' + tabId).append(infoBar, provPg); - - // Create radio buttons for platforms - var hwList = $('
                                Platforms available:
                              '); - var esx = $('
                            • ESX
                            • '); - var kvm = $('
                            • KVM
                            • '); - var zvm = $('
                            • z\/VM
                            • '); - - hwList.append(esx); - hwList.append(kvm); - hwList.append(zvm); - provPg.append(hwList); - - /** - * Ok - */ - var okBtn = createButton('Ok'); - okBtn.bind('click', function(event) { - var userName = $.cookie('xcat_username'); - var tmp = $.cookie('xcat_' + userName + '_usrnodes'); - - // Get maximun number for nodes from cookie - var nodes = ''; - var maxVM = 0; - if (tmp.length) { - nodes = tmp.split(','); - maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm')); - - // Do not allow user to clone if the maximum number of VMs is reached - if (nodes.length >= maxVM) { - var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete unused virtual machines or contact your system administrator request more virtual machines.'); - warn.prependTo($('#' + tabId)); - return; - } - } - - // Get hardware that was selected - var hw = $(this).parent().find('input[name="hw"]:checked').val(); - var newTabId = hw + 'ProvisionTab'; - - if ($('#' + newTabId).size() > 0){ - serviceTabs.select(newTabId); - } else { - var title = ''; - - // Create an instance of the plugin - var plugin = null; - switch (hw) { - case "kvm": - plugin = new kvmPlugin(); - title = 'KVM'; - break; - case "esx": - plugin = new esxPlugin(); - title = 'ESX'; - break; - case "blade": - plugin = new bladePlugin(); - title = 'BladeCenter'; - break; - case "hmc": - plugin = new hmcPlugin(); - title = 'System p'; - break; - case "ipmi": - plugin = new ipmiPlugin(); - title = 'iDataPlex'; - break; - case "zvm": - plugin = new zvmPlugin(); - title = 'z/VM'; - - // Get zVM host names - $.ajax({ - url : 'lib/srv_cmd.php', - dataType : 'json', - async : false, - data : { - cmd : 'webportal', - tgt : '', - args : 'lszvm', - msg : '' - }, - - success : function(data) { - setzVMCookies(data); - } - }); - - // Get master copies for clone - $.ajax({ - url : 'lib/srv_cmd.php', - dataType : 'json', - async : false, - data : { - cmd : 'webportal', - tgt : '', - args : 'lsgoldenimages', - msg : '' - }, - - success : function(data) { - setGoldenImagesCookies(data); - } - }); - - break; - } - - // Select tab - serviceTabs.add(newTabId, title, '', true); - serviceTabs.select(newTabId); - plugin.loadServiceProvisionPage(newTabId); - } - }); - provPg.append(okBtn); -} - -/** - * Load manage page - * - * @param tabId Tab ID where page will reside - */ -function loadManagePage(tabId) { - // Create manage form - var manageForm = $('
                              '); - - // Append to manage tab - $('#' + tabId).append(manageForm); -} - -/** - * Get the user nodes definitions - */ -function getUserNodesDef() { - var userName = $.cookie('xcat_username'); - var userNodes = $.cookie('xcat_' + 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 { - // Clear the tab before inserting the table - $('#manageTab').append(createWarnBar('No nodes were found belonging to you!')); - } -} - -/** - * Load user nodes definitions into a table - * - * @param data Data from HTTP request - */ -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 = null, 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 attrs2show = new Array('arch', 'groups', 'hcp', 'hostnames', 'ip', 'os', 'userid', 'mgt'); - 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 virtual machines.'); - $('#manageTab').append(infoBar); - - // Insert action bar and nodes datatable - $('#manageTab').append(nodesDT.object()); - - // Turn table into a datatable - $('#' + nodesDTId).dataTable({ - 'iDisplayLength': 50, - 'bLengthChange': false, - "bScrollCollapse": true, - "sScrollY": "400px", - "sScrollX": "110%", - "bAutoWidth": true, - "oLanguage": { - "oPaginate": { - "sNext": "", - "sPrevious": "" - } - } - }); - - // Set datatable header class to add color - // $('.datatable thead').attr('class', 'ui-widget-header'); - - // Do not sort ping, power, and comment column - $('#' + 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'); - } - }); - - // Power softoff - var powerSoftoffLnk = $('Shutdown'); - powerSoftoffLnk.click(function() { - var tgtNodes = getNodesChecked(nodesDTId); - if (tgtNodes) { - powerNode(tgtNodes, 'softoff'); - } - }); - - // Clone - var cloneLnk = $('Clone'); - cloneLnk.click(function() { - var tgtNodes = getNodesChecked(nodesDTId); - if (tgtNodes) { - cloneNode(tgtNodes); - } - }); - - // 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); - } - }); - - // Create action bar - var actionBar = $('
                              ').css('width', '370px'); - - // Prepend menu to datatable - var actionsLnk = $('Actions'); - var refreshLnk = $('Refresh'); - refreshLnk.click(function() { - // Get nodes owned by user - $.ajax( { - url : 'lib/srv_cmd.php', - dataType : 'json', - data : { - cmd : 'tabdump', - tgt : '', - args : 'nodetype', - msg : '' - }, - - success : function(data) { - // Save nodes owned by user - setUserNodes(data); - getNodesCurrentLoad(); - - // Refresh nodes table - var userName = $.cookie('xcat_username'); - var userNodes = $.cookie('xcat_' + 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 { - // Clear the tab before inserting the table - $('#manageTab').children().remove(); - $('#manageTab').append(createWarnBar('You are not managing any node. Try to provision a node.')); - } - } - }); - }); - - var actionMenu = createMenu([cloneLnk, deleteLnk, powerOnLnk, powerOffLnk, powerSoftoffLnk, unlockLnk]); - var menu = createMenu([[actionsLnk, actionMenu], refreshLnk]); - menu.superfish(); - actionBar.append(menu); - - // Set correct theme for action menu - actionMenu.find('li').hover(function() { - setMenu2Theme($(this)); - }, function() { - setMenu2Normal($(this)); - }); - - // Create a division to hold actions menu - var menuDiv = $(''); - $('#' + nodesDTId + '_wrapper').prepend(menuDiv); - menuDiv.append(actionBar); - $('#' + nodesDTId + '_filter').appendTo(menuDiv); - - // 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 - */ -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 - */ -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(); - adjustColumnSize(nodesDTId); -} - -/** - * Refresh power status for each node - * - * @param nodes Nodes to get power status - */ -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 - */ -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(); - adjustColumnSize(nodesDTId); -} - -/** - * Refresh the status of Ganglia for each node - * - * @param nodes Nodes to get Ganglia status - */ -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 - */ -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]); - - if (node) { - // 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(); - adjustColumnSize(nodesDTId); -} - -/** - * Load inventory for given node - * - * @param e Windows event - */ -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 : function(data) { - var args = data.msg.split(','); - - // Get node - var node = args[1].replace('node=', ''); - - // Get the management plugin - var mgt = getNodeAttr(node, 'mgt'); - - // Create an instance of the plugin - var plugin; - switch (mgt) { - case "kvm": - plugin = new kvmPlugin(); - break; - case "esx": - plugin = new esxPlugin(); - break; - case "zvm": - plugin = new zvmPlugin(); - break; - } - - // Select tab - plugin.loadServiceInventory(data); - } - }); - } - - // Select new tab - serviceTabs.select(tabId); -} - -/** - * Set a cookie for group names - * - * @param data Data from HTTP request - */ -function setGroupCookies(data) { - if (data.rsp) { - var groups = new Array(); - - // Index 0 is the table header - var cols, name, ip, hostname, desc, selectable, comments, tmp; - for (var i = 1; i < data.rsp.length; i++) { - // Set default description and selectable - selectable = "no"; - desc = "No description"; - - // 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'), ''); - - // It should return: "description: All machines; network: 10.1.100.0/24;" - comments = cols[4].replace(new RegExp('"', 'g'), ''); - tmp = comments.split('|'); - for (var j = 0; j < tmp.length; j++) { - // Save description - if (tmp[j].indexOf('description:') > -1) { - desc = tmp[j].replace('description:', ''); - desc = jQuery.trim(desc); - } - - // Is the group selectable? - if (tmp[j].indexOf('selectable:') > -1) { - selectable = tmp[j].replace('selectable:', ''); - selectable = jQuery.trim(selectable); - } - } - - // Save groups that are selectable - if (selectable == "yes") - 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('xcat_srv_groups', groups, { expires: exDate, path: '/xcat', secure:true }); - } -} - -/** - * Set a cookie for the OS images - * - * @param data Data from HTTP request - */ -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; - var desc, selectable, tmp; - // Get column index for each attribute - 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 install boot - if (provMethod.indexOf('install') > -1) { - if (osComments) { - // Only enable images where description and selectable comments exist - // Set default description and selectable - selectable = "no"; - desc = "No description"; - - tmp = osComments.split('|'); - for (var j = 0; j < tmp.length; j++) { - // Save description - if (tmp[j].indexOf('description:') > -1) { - desc = tmp[j].replace('description:', ''); - desc = jQuery.trim(desc); - } - - // Is the image selectable? - if (tmp[j].indexOf('selectable:') > -1) { - selectable = tmp[j].replace('selectable:', ''); - selectable = jQuery.trim(selectable); - } - } - - // Save images that are selectable - if (selectable == "yes") - imageNames.push(osImage + ':' + desc); - } - - profilesHash[profile] = 1; - osVersHash[osVer] = 1; - osArchsHash[osArch] = 1; - } - } - - // Save image names in a cookie - $.cookie('xcat_srv_imagenames', imageNames); - - // Save profiles in a cookie - var tmp = new Array; - for (var key in profilesHash) { - tmp.push(key); - } - $.cookie('xcat_srv_profiles', tmp); - - // Save OS versions in a cookie - tmp = new Array; - for (var key in osVersHash) { - tmp.push(key); - } - $.cookie('xcat_srv_osvers', tmp); - - // Save OS architectures in a cookie - tmp = new Array; - for (var key in osArchsHash) { - tmp.push(key); - } - $.cookie('xcat_srv_osarchs', tmp); -} - - - -/** - * Set a cookie for user nodes - * - * @param data Data from HTTP request - */ -function setUserNodes(data) { - if (data.rsp) { - // Get user name that is logged in - var userName = $.cookie('xcat_username'); - 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'), ''); - - // Comments can contain the owner and description - var comments = new Array(); - if (cols[7].indexOf(';') > -1) { - comments = cols[7].replace(new RegExp('"', 'g'), '').split(';'); - } else { - comments.push(cols[7].replace(new RegExp('"', 'g'), '')); - } - - // Extract the owner - var owner; - for (var j in comments) { - if (comments[j].indexOf('owner:') > -1) { - owner = comments[j].replace('owner:', ''); - - if (owner == userName) { - usrNodes.push(node); - } - - break; - } - } - } // End of for - - // Set cookie to expire in 240 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (240 * 60 * 1000)); - $.cookie('xcat_' + userName + '_usrnodes', usrNodes, { expires: exDate, path: '/xcat', secure:true }); - } // End of if -} - -/** - * Power on a given node - * - * @param tgtNodes Node to power on or off - * @param power2 Power node to given state - */ -function powerNode(tgtNodes, power2) { - // Show power loader - var nodesDTId = 'userNodesDT'; - var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)'); - powerCol.find('img').show(); - - var nodes = tgtNodes.split(','); - for (var n in nodes) { - // Get hardware that was selected - var hw = getUserNodeAttr(nodes[n], 'mgt'); - - // Change to power softoff (to gracefully shutdown) - switch (hw) { - case "blade": - break; - case "hmc": - break; - case "ipmi": - break; - case "zvm": - if (power2 == 'off') { - power2 = 'softoff'; - } - - break; - } - } - - $.ajax({ - url : 'lib/srv_cmd.php', - dataType : 'json', - data : { - cmd : 'rpower', - tgt : tgtNodes, - args : power2, - msg : tgtNodes - }, - - success : updatePowerStatus - }); -} - -/** - * Update power status of a node in the datatable - * - * @param data Data from HTTP request - */ -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]); - } - } - - var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)'); - powerCol.find('img').hide(); - adjustColumnSize(nodesDTId); -} - -/** - * Turn on monitoring for a given node - * - * @param node Node to monitor on or off - * @param monitor Monitor state, on or off - */ -function monitorNode(node, monitor) { - // Show ganglia loader - var nodesDTId = 'userNodesDT'; - var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); - gangliaCol.find('img').show(); - - if (monitor == 'on') { - 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 clone node - * - * @param tgtNodes Nodes to clone - */ -function cloneNode(tgtNodes) { - var userName = $.cookie('xcat_username'); - var nodes = tgtNodes.split(','); - var tmp = $.cookie('xcat_' + userName + '_usrnodes'); - var usrNodes = tmp.split(','); - - var maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm')); - - // Do not allow user to clone if the maximum number of VMs is reached - if (usrNodes.length >= maxVM) { - var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete un-used virtual machines or contact your system administrator request more virtual machines.'); - warn.prependTo($('#manageTab')); - return; - } - - 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 "kvm": - plugin = new kvmPlugin(); - break; - case "esx": - plugin = new esxPlugin(); - break; - case "zvm": - plugin = new zvmPlugin(); - break; - } - - // Clone node - plugin.serviceClone(nodes[n]); - } -} - - -/** - * Open a dialog to delete node - * - * @param tgtNodes Nodes to delete - */ -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 of node - var dialog = $('
                              '); - var warn = createWarnBar('Are you sure you want to delete ' + tgtNodesStr + '?'); - dialog.append(warn); - - // Open dialog - dialog.dialog({ - title: "Confirm", - modal: true, - close: function(){ - $(this).remove(); - }, - 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 - */ -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('
                              '); - unlockForm.append('
                              '); - 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, - close: function(){ - $(this).remove(); - }, - 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('xcat_username'); - var nodes = $.cookie('xcat_' + 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 - */ -function getMonitorMetrics(node) { - // Inventory tab should have this fieldset already created - // e.g.
                              - $('#' + node + '_monitor').children('div').remove(); - - // Before trying to get the metrics, check if Ganglia is running - $.ajax({ - url : 'lib/srv_cmd.php', - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'gangliastatus;' + node, - msg : '' - }, - - success: function(data) { - var ganglia = data.rsp; - var node, status; - - // Get the ganglia 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]); - - if (node && status == 'on') { - // 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 - }); - } else if (node && status == 'off') { - var info = createInfoBar('Ganglia monitoring is disabled for this node'); - $('#' + node + '_monitor').append(info.css('width', '300px')); - } - } // End of for - } // End of function - }); -} - -/** - * Draw monitoring charts based on node metrics - * - * @param data Data returned from HTTP request - */ -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 - */ -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 - */ -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 - */ -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 - */ -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 - */ -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 - } - }); -} - -/** - * Get an attribute of a given node - * - * @param node The node - * @param attrName The attribute - * @return The attribute of the node - */ -function getNodeAttr(node, attrName) { - // Get the row - var row = $('[id=' + node + ']').parents('tr'); - - // Search for the column containing the attribute - var attrCol = null; - - 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 ''; - } -} - -/** - * Set the maximum number of VMs a user could have - */ -function setMaxVM() { - var userName = $.cookie('xcat_username'); - - $.ajax( { - url : 'lib/srv_cmd.php', - dataType : 'json', - data : { - cmd : 'webportal', - tgt : '', - args : 'getmaxvm;' + userName, - msg : '' - }, - - success : function(data) { - // Get response - var rsp = jQuery.trim(data.rsp); - rsp = rsp.replace('Max allowed:', ''); - - // Set cookie to expire in 60 minutes - var exDate = new Date(); - exDate.setTime(exDate.getTime() + (240 * 60 * 1000)); - $.cookie('xcat_' + userName + '_maxvm', rsp, { expires: exDate }); - } - }); +/** + * Global variables + */ +var serviceTabs; +var nodeName; +var nodePath; +var nodeStatus; +var gangliaTimer; + +/** + * Initialize service page + */ +function initServicePage() { + // Load theme + var theme = $.cookie('xcat_theme'); + if (theme) { + switch (theme) { + case 'cupertino': + includeCss("css/themes/jquery-ui-cupertino.css"); + break; + case 'dark_hive': + includeCss("css/themes/jquery-ui-dark_hive.css"); + break; + case 'redmond': + includeCss("css/themes/jquery-ui-redmond.css"); + break; + case 'start': + includeCss("css/themes/jquery-ui-start.css"); + break; + case 'sunny': + includeCss("css/themes/jquery-ui-sunny.css"); + break; + case 'ui_dark': + includeCss("css/themes/jquery-ui-ui_darkness.css"); + break; + default: + includeCss("css/themes/jquery-ui-start.css"); + } + } else { + includeCss("css/themes/jquery-ui-start.css"); + } + + // Load jQuery stylesheets + includeCss("css/jquery.dataTables.css"); + includeCss("css/superfish.css"); + includeCss("css/jstree.css"); + includeCss("css/jquery.jqplot.css"); + + // Load custom stylesheet + includeCss("css/style.css"); + + // 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"); + + // Custom plugins + includeJs("js/custom/esx.js"); + includeJs("js/custom/kvm.js"); + includeJs("js/custom/zvm.js"); + + // Enable settings link + $('#xcat_settings').click(function() { + openSettings(); + }); + + // Show service page + $("#content").children().remove(); + includeJs("js/service/utils.js"); + loadServicePage(); + + // Initialize tab index history + $.cookie('xcat_tabindex_history', '0,0', { path: '/xcat', secure:true }); +} + +/** + * 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); + + // Get nodes owned by user + $.ajax( { + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'nodetype', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setUserNodes(data); + setMaxVM(); + getUserNodesDef(); + getNodesCurrentLoad(); + loadManagePage(manageTabId); + } + }); + + // Get OS image names + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + async : true, + data : { + cmd : 'tabdump', + tgt : '', + args : 'osimage', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setOSImageCookies(data); + } + }); + + // Get contents of hosts table + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + async : true, + data : { + cmd : 'tabdump', + tgt : '', + args : 'hosts', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setGroupCookies(data); + } + }); + + var provTabId = 'provisionTab'; + serviceTabs.add(provTabId, 'Provision', '', false); + loadServiceProvisionPage(provTabId); + + serviceTabs.select(manageTabId); +} + +/** + * Load the service portal's provision page + * + * @param tabId Tab ID where page will reside + */ +function loadServiceProvisionPage(tabId) { + // Create info bar + var infoBar = createInfoBar('Select a platform to provision a node on, then click Ok.'); + + // Create provision page + var provPg = $('
                              '); + $('#' + tabId).append(infoBar, provPg); + + // Create radio buttons for platforms + var hwList = $('
                                Platforms available:
                              '); + var esx = $('
                            • ESX
                            • '); + var kvm = $('
                            • KVM
                            • '); + var zvm = $('
                            • z\/VM
                            • '); + + hwList.append(esx); + hwList.append(kvm); + hwList.append(zvm); + provPg.append(hwList); + + /** + * Ok + */ + var okBtn = createButton('Ok'); + okBtn.bind('click', function(event) { + var userName = $.cookie('xcat_username'); + var tmp = $.cookie('xcat_' + userName + '_usrnodes'); + + // Get maximun number for nodes from cookie + var nodes = ''; + var maxVM = 0; + if (tmp.length) { + nodes = tmp.split(','); + maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm')); + + // Do not allow user to clone if the maximum number of VMs is reached + if (nodes.length >= maxVM) { + var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete unused virtual machines or contact your system administrator request more virtual machines.'); + warn.prependTo($('#' + tabId)); + return; + } + } + + // Get hardware that was selected + var hw = $(this).parent().find('input[name="hw"]:checked').val(); + var newTabId = hw + 'ProvisionTab'; + + if ($('#' + newTabId).size() > 0){ + serviceTabs.select(newTabId); + } else { + var title = ''; + + // Create an instance of the plugin + var plugin = null; + switch (hw) { + case "kvm": + plugin = new kvmPlugin(); + title = 'KVM'; + break; + case "esx": + plugin = new esxPlugin(); + title = 'ESX'; + break; + case "blade": + plugin = new bladePlugin(); + title = 'BladeCenter'; + break; + case "hmc": + plugin = new hmcPlugin(); + title = 'System p'; + break; + case "ipmi": + plugin = new ipmiPlugin(); + title = 'iDataPlex'; + break; + case "zvm": + plugin = new zvmPlugin(); + title = 'z/VM'; + + // Get zVM host names + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + async : false, + data : { + cmd : 'webportal', + tgt : '', + args : 'lszvm', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setzVMCookies(data); + } + }); + + // Get master copies for clone + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + async : false, + data : { + cmd : 'webportal', + tgt : '', + args : 'lsgoldenimages', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + setGoldenImagesCookies(data); + } + }); + + break; + } + + // Select tab + serviceTabs.add(newTabId, title, '', true); + serviceTabs.select(newTabId); + plugin.loadServiceProvisionPage(newTabId); + } + }); + provPg.append(okBtn); +} + +/** + * Load manage page + * + * @param tabId Tab ID where page will reside + */ +function loadManagePage(tabId) { + // Create manage form + var manageForm = $('
                              '); + + // Append to manage tab + $('#' + tabId).append(manageForm); +} + +/** + * Get the user nodes definitions + */ +function getUserNodesDef() { + var userName = $.cookie('xcat_username'); + var userNodes = $.cookie('xcat_' + userName + '_usrnodes'); + if (userNodes) { + // Get nodes definitions + $.ajax( { + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : userNodes, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadNodesTable(data); + } + }); + } else { + // Clear the tab before inserting the table + $('#manageTab').append(createWarnBar('No nodes were found belonging to you!')); + } +} + +/** + * Load user nodes definitions into a table + * + * @param data Data from HTTP request + */ +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 = null, 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 attrs2show = new Array('arch', 'groups', 'hcp', 'hostnames', 'ip', 'os', 'userid', 'mgt'); + 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 virtual machines.'); + $('#manageTab').append(infoBar); + + // Insert action bar and nodes datatable + $('#manageTab').append(nodesDT.object()); + + // Turn table into a datatable + $('#' + nodesDTId).dataTable({ + 'iDisplayLength': 50, + 'bLengthChange': false, + "bScrollCollapse": true, + "sScrollY": "400px", + "sScrollX": "110%", + "bAutoWidth": true, + "oLanguage": { + "oPaginate": { + "sNext": "", + "sPrevious": "" + } + } + }); + + // Set datatable header class to add color + // $('.datatable thead').attr('class', 'ui-widget-header'); + + // Do not sort ping, power, and comment column + $('#' + 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'); + } + }); + + // Power softoff + var powerSoftoffLnk = $('Shutdown'); + powerSoftoffLnk.click(function() { + var tgtNodes = getNodesChecked(nodesDTId); + if (tgtNodes) { + powerNode(tgtNodes, 'softoff'); + } + }); + + // Clone + var cloneLnk = $('Clone'); + cloneLnk.click(function() { + var tgtNodes = getNodesChecked(nodesDTId); + if (tgtNodes) { + cloneNode(tgtNodes); + } + }); + + // 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); + } + }); + + // Create action bar + var actionBar = $('
                              ').css('width', '370px'); + + // Prepend menu to datatable + var actionsLnk = $('Actions'); + var refreshLnk = $('Refresh'); + refreshLnk.click(function() { + // Get nodes owned by user + $.ajax( { + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'tabdump', + tgt : '', + args : 'nodetype', + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + // Save nodes owned by user + setUserNodes(data); + getNodesCurrentLoad(); + + // Refresh nodes table + var userName = $.cookie('xcat_username'); + var userNodes = $.cookie('xcat_' + userName + '_usrnodes'); + if (userNodes) { + // Get nodes definitions + $.ajax( { + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'lsdef', + tgt : '', + args : userNodes, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + loadNodesTable(data); + } + }); + } else { + // Clear the tab before inserting the table + $('#manageTab').children().remove(); + $('#manageTab').append(createWarnBar('You are not managing any node. Try to provision a node.')); + } + } + }); + }); + + var actionMenu = createMenu([cloneLnk, deleteLnk, powerOnLnk, powerOffLnk, powerSoftoffLnk, unlockLnk]); + var menu = createMenu([[actionsLnk, actionMenu], refreshLnk]); + menu.superfish(); + actionBar.append(menu); + + // Set correct theme for action menu + actionMenu.find('li').hover(function() { + setMenu2Theme($(this)); + }, function() { + setMenu2Normal($(this)); + }); + + // Create a division to hold actions menu + var menuDiv = $(''); + $('#' + nodesDTId + '_wrapper').prepend(menuDiv); + menuDiv.append(actionBar); + $('#' + nodesDTId + '_filter').appendTo(menuDiv); + + // 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 + */ +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 : function(data) { + data = decodeRsp(data); + loadNodePing(data); + } + }); +} + +/** + * Load node ping status for each node + * + * @param data Data returned from HTTP request + */ +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(); + adjustColumnSize(nodesDTId); +} + +/** + * Refresh power status for each node + * + * @param nodes Nodes to get power status + */ +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 : function(data) { + data = decodeRsp(data); + loadPowerStatus(data); + } + }); +} + +/** + * Load power status for each node + * + * @param data Data returned from HTTP request + */ +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(); + adjustColumnSize(nodesDTId); +} + +/** + * Refresh the status of Ganglia for each node + * + * @param nodes Nodes to get Ganglia status + */ +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 : function(data) { + data = decodeRsp(data); + loadGangliaStatus(data); + } + }); +} + +/** + * Load the status of Ganglia for a given group + * + * @param data Data returned from HTTP request + */ +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]); + + if (node) { + // 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(); + adjustColumnSize(nodesDTId); +} + +/** + * Load inventory for given node + * + * @param e Windows event + */ +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 : function(data) { + data = decodeRsp(data); + var args = data.msg.split(','); + + // Get node + var node = args[1].replace('node=', ''); + + // Get the management plugin + var mgt = getNodeAttr(node, 'mgt'); + + // Create an instance of the plugin + var plugin; + switch (mgt) { + case "kvm": + plugin = new kvmPlugin(); + break; + case "esx": + plugin = new esxPlugin(); + break; + case "zvm": + plugin = new zvmPlugin(); + break; + } + + // Select tab + plugin.loadServiceInventory(data); + } + }); + } + + // Select new tab + serviceTabs.select(tabId); +} + +/** + * Set a cookie for group names + * + * @param data Data from HTTP request + */ +function setGroupCookies(data) { + if (data.rsp) { + var groups = new Array(); + + // Index 0 is the table header + var cols, name, ip, hostname, desc, selectable, comments, tmp; + for (var i = 1; i < data.rsp.length; i++) { + // Set default description and selectable + selectable = "no"; + desc = "No description"; + + // 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'), ''); + + // It should return: "description: All machines; network: 10.1.100.0/24;" + comments = cols[4].replace(new RegExp('"', 'g'), ''); + tmp = comments.split('|'); + for (var j = 0; j < tmp.length; j++) { + // Save description + if (tmp[j].indexOf('description:') > -1) { + desc = tmp[j].replace('description:', ''); + desc = jQuery.trim(desc); + } + + // Is the group selectable? + if (tmp[j].indexOf('selectable:') > -1) { + selectable = tmp[j].replace('selectable:', ''); + selectable = jQuery.trim(selectable); + } + } + + // Save groups that are selectable + if (selectable == "yes") + 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('xcat_srv_groups', groups, { expires: exDate, path: '/xcat', secure:true }); + } +} + +/** + * Set a cookie for the OS images + * + * @param data Data from HTTP request + */ +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; + var desc, selectable, tmp; + // Get column index for each attribute + 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 install boot + if (provMethod.indexOf('install') > -1) { + if (osComments) { + // Only enable images where description and selectable comments exist + // Set default description and selectable + selectable = "no"; + desc = "No description"; + + tmp = osComments.split('|'); + for (var j = 0; j < tmp.length; j++) { + // Save description + if (tmp[j].indexOf('description:') > -1) { + desc = tmp[j].replace('description:', ''); + desc = jQuery.trim(desc); + } + + // Is the image selectable? + if (tmp[j].indexOf('selectable:') > -1) { + selectable = tmp[j].replace('selectable:', ''); + selectable = jQuery.trim(selectable); + } + } + + // Save images that are selectable + if (selectable == "yes") + imageNames.push(osImage + ':' + desc); + } + + profilesHash[profile] = 1; + osVersHash[osVer] = 1; + osArchsHash[osArch] = 1; + } + } + + // Save image names in a cookie + $.cookie('xcat_srv_imagenames', imageNames); + + // Save profiles in a cookie + var tmp = new Array; + for (var key in profilesHash) { + tmp.push(key); + } + $.cookie('xcat_srv_profiles', tmp); + + // Save OS versions in a cookie + tmp = new Array; + for (var key in osVersHash) { + tmp.push(key); + } + $.cookie('xcat_srv_osvers', tmp); + + // Save OS architectures in a cookie + tmp = new Array; + for (var key in osArchsHash) { + tmp.push(key); + } + $.cookie('xcat_srv_osarchs', tmp); +} + + + +/** + * Set a cookie for user nodes + * + * @param data Data from HTTP request + */ +function setUserNodes(data) { + if (data.rsp) { + // Get user name that is logged in + var userName = $.cookie('xcat_username'); + 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'), ''); + + // Comments can contain the owner and description + var comments = new Array(); + if (cols[7].indexOf(';') > -1) { + comments = cols[7].replace(new RegExp('"', 'g'), '').split(';'); + } else { + comments.push(cols[7].replace(new RegExp('"', 'g'), '')); + } + + // Extract the owner + var owner; + for (var j in comments) { + if (comments[j].indexOf('owner:') > -1) { + owner = comments[j].replace('owner:', ''); + + if (owner == userName) { + usrNodes.push(node); + } + + break; + } + } + } // End of for + + // Set cookie to expire in 240 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (240 * 60 * 1000)); + $.cookie('xcat_' + userName + '_usrnodes', usrNodes, { expires: exDate, path: '/xcat', secure:true }); + } // End of if +} + +/** + * Power on a given node + * + * @param tgtNodes Node to power on or off + * @param power2 Power node to given state + */ +function powerNode(tgtNodes, power2) { + // Show power loader + var nodesDTId = 'userNodesDT'; + var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)'); + powerCol.find('img').show(); + + var nodes = tgtNodes.split(','); + for (var n in nodes) { + // Get hardware that was selected + var hw = getUserNodeAttr(nodes[n], 'mgt'); + + // Change to power softoff (to gracefully shutdown) + switch (hw) { + case "blade": + break; + case "hmc": + break; + case "ipmi": + break; + case "zvm": + if (power2 == 'off') { + power2 = 'softoff'; + } + + break; + } + } + + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'rpower', + tgt : tgtNodes, + args : power2, + msg : tgtNodes + }, + + success : function(data) { + data = decodeRsp(data); + updatePowerStatus(data); + } + }); +} + +/** + * Update power status of a node in the datatable + * + * @param data Data from HTTP request + */ +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]); + } + } + + var powerCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(3)'); + powerCol.find('img').hide(); + adjustColumnSize(nodesDTId); +} + +/** + * Turn on monitoring for a given node + * + * @param node Node to monitor on or off + * @param monitor Monitor state, on or off + */ +function monitorNode(node, monitor) { + // Show ganglia loader + var nodesDTId = 'userNodesDT'; + var gangliaCol = $('#' + nodesDTId + '_wrapper .dataTables_scrollHead .datatable thead tr th:eq(4)'); + gangliaCol.find('img').show(); + + if (monitor == 'on') { + 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) { + data = decodeRsp(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) { + data = decodeRsp(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) { + data = decodeRsp(data); + refreshGangliaStatus(data.msg); + } + }); + } + } +} + +/** + * Open a dialog to clone node + * + * @param tgtNodes Nodes to clone + */ +function cloneNode(tgtNodes) { + var userName = $.cookie('xcat_username'); + var nodes = tgtNodes.split(','); + var tmp = $.cookie('xcat_' + userName + '_usrnodes'); + var usrNodes = tmp.split(','); + + var maxVM = parseInt($.cookie('xcat_' + userName + '_maxvm')); + + // Do not allow user to clone if the maximum number of VMs is reached + if (usrNodes.length >= maxVM) { + var warn = createWarnBar('You have reached the maximum number of virtual machines allowed (' + maxVM + '). Delete un-used virtual machines or contact your system administrator request more virtual machines.'); + warn.prependTo($('#manageTab')); + return; + } + + 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 "kvm": + plugin = new kvmPlugin(); + break; + case "esx": + plugin = new esxPlugin(); + break; + case "zvm": + plugin = new zvmPlugin(); + break; + } + + // Clone node + plugin.serviceClone(nodes[n]); + } +} + + +/** + * Open a dialog to delete node + * + * @param tgtNodes Nodes to delete + */ +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 of node + var dialog = $('
                              '); + var warn = createWarnBar('Are you sure you want to delete ' + tgtNodesStr + '?'); + dialog.append(warn); + + // Open dialog + dialog.dialog({ + title: "Confirm", + modal: true, + close: function(){ + $(this).remove(); + }, + 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) { + data = decodeRsp(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) { + data = decodeRsp(data); + setUserNodes(data); + } + }); + } + }); + + $(this).dialog("close"); + }, + "No": function() { + $(this).dialog("close"); + } + } + }); +} + +/** + * Unlock a node by setting the ssh keys + * + * @param tgtNodes Nodes to unlock + */ +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('
                              '); + unlockForm.append('
                              '); + 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, + close: function(){ + $(this).remove(); + }, + 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) { + data = decodeRsp(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('xcat_username'); + var nodes = $.cookie('xcat_' + userName + '_usrnodes'); + + // Get nodes current status + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'gangliacurrent;node;' + nodes, + msg : '' + }, + + success: function(data) { + data = decodeRsp(data); + saveNodeLoad(data); + } + }); +} + +/** + * 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 + */ +function getMonitorMetrics(node) { + // Inventory tab should have this fieldset already created + // e.g.
                              + $('#' + node + '_monitor').children('div').remove(); + + // Before trying to get the metrics, check if Ganglia is running + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'gangliastatus;' + node, + msg : '' + }, + + success: function(data) { + data = decodeRsp(data); + var ganglia = data.rsp; + var node, status; + + // Get the ganglia 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]); + + if (node && status == 'on') { + // Get monitoring metrics + $.ajax({ + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'gangliashow;' + nodePath[node] + ';hour;_summary_', + msg : node + }, + + success: function(data) { + data = decodeRsp(data); + drawMonitoringCharts(data); + } + }); + } else if (node && status == 'off') { + var info = createInfoBar('Ganglia monitoring is disabled for this node'); + $('#' + node + '_monitor').append(info.css('width', '300px')); + } + } // End of for + } // End of function + }); +} + +/** + * Draw monitoring charts based on node metrics + * + * @param data Data returned from HTTP request + */ +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 + */ +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 + */ +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 + */ +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 + */ +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 + */ +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 + } + }); +} + +/** + * Get an attribute of a given node + * + * @param node The node + * @param attrName The attribute + * @return The attribute of the node + */ +function getNodeAttr(node, attrName) { + // Get the row + var row = $('[id=' + node + ']').parents('tr'); + + // Search for the column containing the attribute + var attrCol = null; + + 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 ''; + } +} + +/** + * Set the maximum number of VMs a user could have + */ +function setMaxVM() { + var userName = $.cookie('xcat_username'); + + $.ajax( { + url : 'lib/srv_cmd.php', + dataType : 'json', + data : { + cmd : 'webportal', + tgt : '', + args : 'getmaxvm;' + userName, + msg : '' + }, + + success : function(data) { + data = decodeRsp(data); + // Get response + var rsp = jQuery.trim(data.rsp); + rsp = rsp.replace('Max allowed:', ''); + + // Set cookie to expire in 60 minutes + var exDate = new Date(); + exDate.setTime(exDate.getTime() + (240 * 60 * 1000)); + $.cookie('xcat_' + userName + '_maxvm', rsp, { expires: exDate }); + } + }); } \ No newline at end of file diff --git a/xCAT-UI/js/ui.js b/xCAT-UI/js/ui.js index 771fa5d65..3b5da6ba2 100644 --- a/xCAT-UI/js/ui.js +++ b/xCAT-UI/js/ui.js @@ -1,1068 +1,1101 @@ -/** - * Tab constructor - * - * @param tabId - * Tab ID - * @param tabName - * Tab name - * @return Nothing - */ -var Tab = function(tabId) { - this.tabId = tabId; - this.tabName = null; - this.tab = null; -}; - -/** - * Initialize the tab - * - * @param tabName Tab name to initialize - */ -Tab.prototype.init = function() { - // Create a division containing the tab - this.tab = $('
                              '); - var tabList = $(''); - var tabItem = $('
                            • Dummy tab item
                            • '); - tabList.append(tabItem); - this.tab.append(tabList); - - // Create a template with close button - var tabs = this.tab.tabs(); - - tabs.bind('tabsselect', function(event, ui){ - // Save the order tabs were selected - var order; - if ($.cookie('xcat_tabindex_history')) { - order = $.cookie('xcat_tabindex_history').split(','); - order[1] = order[0]; // Set index 1 to last selected tab - order[0] = ui.index; // Set index 0 to currently selected tab - } else { - // Create an array to track the tab selected - order = new Array; - order[0] = ui.index; - order[1] = ui.index; - } - - $.cookie('xcat_tabindex_history', order, { path: '/xcat', secure:true }); - }); - - // Remove dummy tab - this.tab.tabs("remove", 0); - - // Hide tab - this.tab.hide(); -}; - -/** - * Return the tab object - * - * @return Object representing the tab - */ -Tab.prototype.object = function() { - return this.tab; -}; - -/** - * Add a new tab - * - * @param tabId Tab ID - * @param tabName Tab name - * @param tabCont Tab content - * @param closeable Is tab closeable - */ -Tab.prototype.add = function(tabId, tabName, tabCont, closeable) { - // Show tab - if (this.tab.css("display") == "none") { - this.tab.show(); - } - - var newTab = $('
                              '); - newTab.append(tabCont); - this.tab.append(newTab); - this.tab.tabs("add", "#" + tabId, tabName); - - // Append close button - if (closeable) { - var header = this.tab.find('ul.ui-tabs-nav a[href="#' + tabId +'"]').parent(); - header.append(''); - - // Get this tab - var tabs = this.tab; - var tabLink = 'a[href="\#' + tabId + '"]'; - var thisTab = $(tabLink, tabs).parent(); - - // Close tab when close button is clicked - thisTab.find('span.tab-close').bind('click', function(event) { - var tabIndex = ($('li', tabs).index(thisTab)); - - // Do not remove first tab - if (tabIndex != 0) { - // Go back to last tab if user is trying to close currently selected tab - if (tabs.tabs('option', 'selected') == tabIndex) { - // Get last selected tab from history - var order = $.cookie('xcat_tabindex_history').split(','); - if (order[1]) { - tabs.tabs('select', parseInt(order[1])); - } else { - tabs.tabs('select', 0); - } - } - - tabs.tabs('remove', tabIndex); - } - }); - } -}; - -/** - * Select a tab - * - * @param id Tab ID to select - */ -Tab.prototype.select = function(id) { - this.tab.tabs("select", "#" + id); -}; - -/** - * Remove a tab - * - * @param id Tab ID to remove - */ -Tab.prototype.remove = function(id) { - var selectorStr = 'a[href="\#' + id + '"]'; - var selectTab = $(selectorStr, this.tab).parent(); - var index = ($('li', this.tab).index(selectTab)); - this.tab.tabs("remove", index); -}; - -/** - * Table constructor - * - * @param tabId Tab ID - * @param tabName Tab name - */ -var Table = function(tableId) { - if ($('#' + tableId).length) { - this.tableId = tableId; - this.table = $('#' + tableId); - } else { - this.tableId = tableId; - this.table = null; - } -}; - -/** - * Initialize the table - * - * @param Headers Array of table headers - */ -Table.prototype.init = function(headers) { - // Create a table - this.table = $('
                              '); - var thead = $(''); - var headRow = $(''); - - // Append headers - for (var i in headers) { - headRow.append('' + headers[i] + ''); - } - - thead.append(headRow); - this.table.append(thead); - - // Append table body - var tableBody = $(''); - this.table.append(tableBody); -}; - -/** - * Return the table object - * - * @return Object representing the table - */ -Table.prototype.object = function() { - return this.table; -}; - -/** - * Add a row to the table - * - * @param rowCont Array of table row contents - */ -Table.prototype.add = function(rowCont) { - // Create table row - var tableRow = $(''); - - // Create a column for each content - var tableCol; - for (var i in rowCont) { - tableCol = $(''); - tableCol.append(rowCont[i]); - tableRow.append(tableCol); - } - - // Append table row to table - this.table.find('tbody').append(tableRow); -}; - -/** - * Add a footer to the table - * - * @param rowCont Array of table row contents - */ -Table.prototype.addFooter = function(rowCont) { - // Create table row - var tableFoot = $(''); - tableFoot.append(rowCont); - - // Append table row to table - this.table.append(tableFoot); -}; - -/** - * Remove a row from the table - */ -Table.prototype.remove = function(id) { - // To be continued -}; - -/** - * Datatable class constructor - * - * @param tabId Tab ID - * @param tabName Tab name - */ -var DataTable = function(tableId) { - this.dataTableId = tableId; - this.dataTable = null; -}; - -/** - * Initialize the datatable - * - * @param Headers Array of table headers - */ -DataTable.prototype.init = function(headers) { - // Create a table - this.dataTable = $('
                              '); - var thead = $(''); - var headRow = $(''); - - // Append headers - for (var i in headers) { - headRow.append('' + headers[i] + ''); - } - - thead.append(headRow); - this.dataTable.append(thead); - - // Append table body - var tableBody = $(''); - this.dataTable.append(tableBody); -}; - -/** - * Return the datatable object - * - * @return Object representing the table - */ -DataTable.prototype.object = function() { - return this.dataTable; -}; - -/** - * Add a row to the datatable - * - * @param rowCont Array of table row contents - */ -DataTable.prototype.add = function(rowCont) { - // Create table row - var tableRow = $(''); - - // Create a column for each content - var tableCol; - for (var i in rowCont) { - tableCol = $(''); - tableCol.append(rowCont[i]); - tableRow.append(tableCol); - } - - // Append table row to table - this.dataTable.find('tbody').append(tableRow); -}; - -/** - * Create status bar - * - * @param barId Status bar ID - */ -function createStatusBar(barId) { - // Do not change the background color or color! This is handled by the theme - // the user selects. - var statusBar = $('
                              ').css({ - 'margin-bottom': '5px', - 'min-height': '30px', - 'max-height': '150px', - 'overflow': 'auto' - }); - - // Create info icon - var icon = $('').css({ - 'display': 'inline-block', - 'margin': '10px 5px', - 'vertical-align': 'top' - }); - - // Create message section - var msg = $('
                              ').css({ - 'display': 'inline-block', - 'margin': '10px 0px', - 'width': '90%' - }); - - // Create hide button - var hide = $('').css({ - 'display': 'inline-block', - 'float': 'right', - 'cursor': 'pointer' - }).click(function() { - // Remove info box on-click - $(this).parent().hide(); - }); - - statusBar.append(icon); - statusBar.append(msg); - statusBar.append(hide); - return statusBar; -} - -/** - * Create info bar - * - * @param msg Info message - * @return Info bar - */ -function createInfoBar(msg) { - // Do not change the background color or color! This is handled by the theme - // the user selects. - var infoBar = $('
                              ').css({ - 'margin': '5px 0px' - }); - var icon = $('').css({ - 'display': 'inline-block', - 'margin': '10px 5px' - }); - var barMsg = $('

                              ' + msg + '

                              ').css({ - 'display': 'inline-block', - 'width': '90%' - }); - - infoBar.append(icon); - infoBar.append(barMsg); - return infoBar; -} - -/** - * Create warning bar - * - * @param msg Warning message - * @return Warning bar - */ -function createWarnBar(msg) { - var warnBar = $('
                              '); - var icon = $('').css({ - 'display': 'inline-block', - 'margin': '10px 5px' - }); - var barMsg = $('

                              ' + msg + '

                              ').css({ - 'display': 'inline-block', - 'width': '90%' - }); - - warnBar.append(icon); - warnBar.append(barMsg); - return warnBar; -} - -/** - * Create a loader - * - * @param loaderId Loader ID - */ -function createLoader(loaderId) { - var loader = $(''); - return loader; -} - -/** - * Create a button - * - * @param name Name of the button - */ -function createButton(name) { - var button = $('').button(); - return button; -} - -/** - * Create a menu - * - * @param items An array of items to go into the menu - * @return A division containing the menu - */ -function createMenu(items) { - var menu = $(''); - - // Loop through each item - for ( var i in items) { - // Append item to menu - var item = $('
                            • '); - - // If it is a sub menu - if (items[i] instanceof Array) { - // 1st index = Sub menu title - item.append(items[i][0]); - // 2nd index = Sub menu - item.append(items[i][1]); - } else { - item.append(items[i]); - } - - menu.append(item); - } - - return menu; -} - -/** - * Initialize the page - */ -function initPage() { - // Load theme - var theme = $.cookie('xcat_theme'); - if (theme) { - switch (theme) { - case 'cupertino': - includeCss("css/themes/jquery-ui-cupertino.css"); - break; - case 'dark_hive': - includeCss("css/themes/jquery-ui-dark_hive.css"); - break; - case 'redmond': - includeCss("css/themes/jquery-ui-redmond.css"); - break; - case 'start': - includeCss("css/themes/jquery-ui-start.css"); - break; - case 'sunny': - includeCss("css/themes/jquery-ui-sunny.css"); - break; - case 'ui_dark': - includeCss("css/themes/jquery-ui-ui_darkness.css"); - break; - default: - includeCss("css/themes/jquery-ui-start.css"); - } - } else { - includeCss("css/themes/jquery-ui-start.css"); - } - - // Load jQuery stylesheets - includeCss("css/jquery.dataTables.css"); - includeCss("css/superfish.css"); - // includeCss("css/jstree.css"); - includeCss("css/jquery.jqplot.css"); - - // Load custom stylesheet - includeCss("css/style.css"); - - // JQuery plugins - includeJs("js/jquery/jquery.dataTables.min.js"); - includeJs("js/jquery/jquery.form.min.js"); - includeJs("js/jquery/jquery.jeditable.min.js"); - includeJs("js/jquery/jquery.contextmenu.min.js"); - includeJs("js/jquery/superfish.min.js"); - includeJs("js/jquery/hoverIntent.min.js"); - // includeJs("js/jquery/jquery.jstree.min.js"); - includeJs("js/jquery/tooltip.min.js"); - includeJs("js/jquery/jquery.serverBrowser.min.js"); - includeJs("js/jquery/jquery.jqplot.min.js"); - includeJs("js/jquery/jqplot.pieRenderer.min.js"); - includeJs("js/jquery/jqplot.barRenderer.min.js"); - includeJs("js/jquery/jqplot.pointLabels.min.js"); - includeJs("js/jquery/jqplot.categoryAxisRenderer.min.js"); - includeJs("js/jquery/jqplot.dateAxisRenderer.min.js"); - includeJs("js/jquery/jquery.topzindex.min.js"); - - // Page plugins - includeJs("js/configure/configure.js"); - includeJs("js/monitor/monitor.js"); - includeJs("js/nodes/nodes.js"); - includeJs("js/provision/provision.js"); - - // Custom plugins - includeJs("js/custom/esx.js"); - includeJs("js/custom/kvm.js"); - includeJs("js/custom/blade.js"); - includeJs("js/custom/ipmi.js"); - includeJs("js/custom/zvm.js"); - includeJs("js/custom/hmc.js"); - includeJs("js/custom/customUtils.js"); - - // Enable settings link - $('#xcat_settings').click(function() { - openSettings(); - }); - - // Set header to theme - var background = '', color = ''; - var theme = $.cookie('xcat_theme'); - if (theme) { - switch (theme) { - case 'cupertino': - background = '#3BAAE3'; - color = 'white'; - break; - case 'dark_hive': - background = '#0972A5'; - break; - case 'redmond': - background = '#F5F8F9'; - color = '#E17009'; - break; - case 'start': - background = '#6EAC2C'; - break; - case 'sunny': - background = 'white'; - color = '#0074C7'; - break; - case 'ui_dark': - background = '#F58400'; - break; - default: - background = '#6EAC2C'; - } - } else { - background = '#6EAC2C'; - } - - $('#header').addClass('ui-state-default'); - $('#header').css('border', '0px'); - - // Set theme to user span - $('#login_user').css('color', color); - - // Style for selected page - var style = { - 'background-color': background, - 'color': color - }; - - // Get the page being loaded - var url = window.location.pathname; - var page = url.replace('/xcat/', ''); - var headers = $('#header ul li a'); - - // Show the page - $("#content").children().remove(); - if (page == 'configure.php') { - includeJs("js/configure/update.js"); - includeJs("js/configure/service.js"); - includeJs("js/configure/users.js"); - includeJs("js/configure/files.js"); - headers.eq(1).css(style); - loadConfigPage(); - } else if (page == 'provision.php') { - includeJs("js/provision/images.js"); - headers.eq(2).css(style); - loadProvisionPage(); - } else if (page == 'help.php') { - includeJs("js/help/help.js"); - headers.eq(4).css(style); - loadHelpPage(); - } else { - // Load nodes page by default - includeJs("js/nodes/nodeset.js"); - includeJs("js/nodes/rnetboot.js"); - includeJs("js/nodes/updatenode.js"); - includeJs("js/nodes/rscan.js"); - headers.eq(0).css(style); - loadNodesPage(); - } -} - -/** - * Include javascript file in - * - * @param file File to include - */ -function includeJs(file) { - var script = $("head script[src='" + file + "']"); - - // If does not contain the javascript - if (!script.length) { - // Append the javascript to - var script = $(''); - script.attr( { - type : 'text/javascript', - src : file - }); - - $('head').append(script); - } -} - -/** - * Include CSS link in - * - * @param file File to include - */ -function includeCss(file) { - var link = $("head link[href='" + file + "']"); - - // If does not contain the link - if (!link.length) { - // Append the CSS link to - var link = $(''); - link.attr( { - type : 'text/css', - rel : 'stylesheet', - href : file - }); - - $('head').append(link); - } -} - -/** - * Write ajax response to a paragraph - * - * @param rsp Ajax response - * @param pattern Pattern to replace with a break - * @return Paragraph containing ajax response - */ -function writeRsp(rsp, pattern) { - // Create paragraph to hold ajax response - var prg = $('
                              ');
                              -
                              -    for ( var i in rsp) {
                              -        if (rsp[i]) {
                              -            // Create regular expression for given pattern
                              -            // Replace pattern with break
                              -            if (pattern) {
                              -                rsp[i] = rsp[i].replace(new RegExp(pattern, 'g'), '
                              '); - prg.append(rsp[i]); - } else { - prg.append(rsp[i]); - prg.append('
                              '); - } - } - } - - return prg; -} - -/** - * Open a dialog and show given message - * - * @param type Type of dialog, i.e. warn or info - * @param msg Message to show - */ -function openDialog(type, msg) { - var msgDialog = $('
                              '); - var title = ""; - if (type == "warn") { - // Create warning message - msgDialog.append(createWarnBar(msg)); - title = "Warning"; - } else { - // Create info message - msgDialog.append(createInfoBar(msg)); - title = "Info"; - } - - // Open dialog - msgDialog.dialog({ - title: title, - modal: true, - close: function(){ - $(this).remove(); - }, - width: 500, - buttons: { - "Ok": function(){ - $(this).dialog("close"); - } - } - }); -} - -/** - * Create an iframe to hold the output of an xCAT command - * - * @param src The URL of the document to show in the iframe - * @return Info box containing the iframe - */ -function createIFrame(src) { - // Put an iframe inside an info box - var infoBar = $('
                              ').css({ - 'margin-bottom': '5px' - }); - - // Create info and close icons - var icon = $('').css({ - 'display': 'inline-block', - 'margin': '10px 5px' - }); - var close = $('').css({ - 'display': 'inline-block', - 'float': 'right', - 'margin': '10px 5px' - }).click(function() { - // Remove info box on-click - $(this).parent().remove(); - }); - - var iframe = $('').attr('src', src).css({ - 'display': 'block', - 'border': '0px', - 'margin': '10px', - 'width': '100%' - }); - - var loader = createLoader('iLoader').css({ - 'display': 'block', - 'margin': '10px 0px' - }); - - infoBar.append(icon); - infoBar.append($('
                              ').append(loader, iframe)); - infoBar.append(close); - - // Remove loader when done - iframe.load(function() { - loader.remove(); - }); - - return infoBar; -} - - -/** - * Open dialog to set xCAT UI settings - */ -function openSettings() { - // Create form to add node range - var dialog = $('
                              '); - var info = createInfoBar('Select from the following options'); - dialog.append(info); - - var style = { - 'color': 'blue', - 'cursor': 'pointer', - 'padding': '5px' - }; - - var changeThemeOption = $('
                              Change xCAT theme
                              ').css(style); - dialog.append(changeThemeOption); - - var changePasswordOption = $('
                              Change password
                              ').css(style); - dialog.append(changePasswordOption); - - // Open form as a dialog - dialog.dialog({ - modal: true, - close: function(){ - $(this).remove(); - }, - title: 'Settings', - width: 400, - buttons: { - "Cancel": function(){ - $(this).dialog("close"); - } - } - }); - - // Bind to click event - changeThemeOption.click(function() { - dialog.dialog("close"); - changeTheme(); - }); - - changePasswordOption.click(function() { - dialog.dialog("close"); - changePassword(); - }); -} - -/** - * Open dialog to change xCAT theme - */ -function changeTheme() { - // Create form to add node range - var dialog = $('
                              '); - var info = createInfoBar('Select the xCAT theme you desire'); - dialog.append(info); - - // Create select drop down for themes - var oList = $('
                                '); - oList.append($('
                              1. Cupertino
                              2. ')); - oList.append($('
                              3. Dark Hive
                              4. ')); - oList.append($('
                              5. Redmond
                              6. ')); - oList.append($('
                              7. Start (default)
                              8. ')); - oList.append($('
                              9. Sunny
                              10. ')); - oList.append($('
                              11. UI Darkness
                              12. ')); - dialog.append(oList); - - if ($.cookie('xcat_theme')) { - // Select theme - oList.find('input[value="' + $.cookie('xcat_theme') + '"]').attr('checked', true); - } else { - oList.find('input[value="start"]').attr('checked', true); - } - - // Open form as a dialog - dialog.dialog({ - modal: true, - close: function(){ - $(this).remove(); - }, - title: 'xCAT Theme', - width: 400, - buttons: { - "Ok": function(){ - // Save selected theme - var theme = $(this).find('input[name="theme"]:checked').val(); - $.cookie('xcat_theme', theme); // Do not expire cookie, keep it as long as possible - - // Show instructions to apply theme - $(this).empty(); - var info = createInfoBar('You will need to reload this page in order for changes to take effect'); - $(this).append(info); - - // Only show close button - $(this).dialog("option", "buttons", { - "Close" : function() { - $(this).dialog( "close" ); - } - }); - }, - "Cancel": function(){ - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Open dialog to change user password - */ -function changePassword() { - // Create form to add node range - var dialog = $('
                                '); - var info = createInfoBar('Change your password'); - dialog.append(info); - - dialog.append('
                                '); - dialog.append('
                                '); - - // Open form as a dialog - dialog.dialog({ - modal: true, - close: function(){ - $(this).remove(); - }, - title: 'Change Password', - width: 400, - buttons: { - "Ok": function(){ - // Remove any warning messages - $(this).find('.ui-state-error').remove(); - - var errorMessage = ""; - - // Check each input is provided - $('#changePassword input').each(function() { - if (!$(this).val()) { - errorMessage = "Please provide a value for each missing input!"; - } - }); - - // Do not continue if error found - if (errorMessage) { - dialog.prepend(createWarnBar(errorMessage)); - return; - } - - // Check new and confirm passwords match - var user = $.cookie('xcat_username'); - var newPassword = $('#changePassword input[name="newPassword"]').val(); - var confirmPassword = $('#changePassword input[name="confirmPassword"]').val(); - if (newPassword != confirmPassword) { - dialog.prepend(createWarnBar("Please confirm new password!")); - return; - } - - // Change dialog buttons - $('#changePassword').dialog('option', 'buttons', { - 'Close':function(){ - $('#changePassword').dialog('destroy').remove(); - } - }); - - // Send request to change password - var url = window.location.pathname; - var page = url.replace('/xcat/', ''); - var url = 'lib/cmd.php'; - // Service portal does not have access to cmd.php - if (page == 'service.php') - url = 'lib/srv_cmd.php'; - $.ajax( { - url : url, - dataType : 'json', - data : { - cmd : 'webrun', - tgt : '', - args : 'passwd;' + user + ';' + newPassword, - msg : '' - }, - - success : function (data) { - // Show response message - var rspMessage = ""; - for (var i in data.rsp) - rspMessage += data.rsp[i] + "
                                "; - - $('#changePassword').prepend(createInfoBar(rspMessage)); - } - }); - }, - "Cancel": function(){ - $(this).dialog( "close" ); - } - } - }); -} - -/** - * Adjust datatable column size - * - * @param tableId Table ID - */ -function adjustColumnSize(tableId) { - var dTable = $('#' + tableId).dataTable(); - dTable.fnAdjustColumnSizing(); -} - -/** - * Set menu theme - * - * @param menu Menu object - */ -function setMenu2Theme(menu) { - // On hover - var background = '', color = ''; - var theme = $.cookie('xcat_theme'); - if (theme) { - switch (theme) { - case 'cupertino': - background = '#3BAAE3'; - color = 'white'; - break; - case 'dark_hive': - background = '#0972A5'; - break; - case 'redmond': - background = '#F5F8F9'; - color = '#E17009'; - break; - case 'start': - background = '#6EAC2C'; - break; - case 'sunny': - background = 'white'; - color = '#0074C7'; - break; - case 'ui_dark': - background = '#F58400'; - break; - default: - background = '#6EAC2C'; - } - } else { - background = '#6EAC2C'; - } - - menu.css('background', background); - menu.find('a:eq(0)').css('color', color); -} - -/** - * Set menu back to normal before applying theme - * - * @param menu Menu object - */ -function setMenu2Normal(menu) { - // Change back to normal - menu.css('background', ''); - menu.find('a:eq(0)').css('color', ''); -} - -/** - * Get nodes that are checked in a given datatable - * - * @param datatableId The datatable ID - * @return Nodes that were checked - */ -function getNodesChecked(datatableId) { - var tgts = ''; - - // Get nodes that were checked - var nodes = $('#' + datatableId + ' 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; -} - -/** - * Check if return message contains errors - * - * @param msg Return message - * @return 0 If return message contains no errors - * -1 If return message contains errors - */ -function containErrors(msg) { - if (msg.indexOf('Failed') > -1 || msg.indexOf('Error') > -1) { - return -1; - } else { - return 0; - } -} - -/** - * Check if a value is an integer - * - * @param value Value to be checked - * @returns true If value is an integer - false If value is not an integer - */ -function isInteger(value){ - if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) { - return true; - } else { - return false; - } -} +/** + * Tab constructor + * + * @param tabId + * Tab ID + * @param tabName + * Tab name + * @return Nothing + */ +var Tab = function(tabId) { + this.tabId = tabId; + this.tabName = null; + this.tab = null; +}; + +/** + * Initialize the tab + * + * @param tabName Tab name to initialize + */ +Tab.prototype.init = function() { + // Create a division containing the tab + this.tab = $('
                                '); + var tabList = $(''); + var tabItem = $('
                              13. Dummy tab item
                              14. '); + tabList.append(tabItem); + this.tab.append(tabList); + + // Create a template with close button + var tabs = this.tab.tabs(); + + tabs.bind('tabsselect', function(event, ui){ + // Save the order tabs were selected + var order; + if ($.cookie('xcat_tabindex_history')) { + order = $.cookie('xcat_tabindex_history').split(','); + order[1] = order[0]; // Set index 1 to last selected tab + order[0] = ui.index; // Set index 0 to currently selected tab + } else { + // Create an array to track the tab selected + order = new Array; + order[0] = ui.index; + order[1] = ui.index; + } + + $.cookie('xcat_tabindex_history', order, { path: '/xcat', secure:true }); + }); + + // Remove dummy tab + this.tab.tabs("remove", 0); + + // Hide tab + this.tab.hide(); +}; + +/** + * Return the tab object + * + * @return Object representing the tab + */ +Tab.prototype.object = function() { + return this.tab; +}; + +/** + * Add a new tab + * + * @param tabId Tab ID + * @param tabName Tab name + * @param tabCont Tab content + * @param closeable Is tab closeable + */ +Tab.prototype.add = function(tabId, tabName, tabCont, closeable) { + // Show tab + if (this.tab.css("display") == "none") { + this.tab.show(); + } + + var newTab = $('
                                '); + newTab.append(tabCont); + this.tab.append(newTab); + this.tab.tabs("add", "#" + tabId, tabName); + + // Append close button + if (closeable) { + var header = this.tab.find('ul.ui-tabs-nav a[href="#' + tabId +'"]').parent(); + header.append(''); + + // Get this tab + var tabs = this.tab; + var tabLink = 'a[href="\#' + tabId + '"]'; + var thisTab = $(tabLink, tabs).parent(); + + // Close tab when close button is clicked + thisTab.find('span.tab-close').bind('click', function(event) { + var tabIndex = ($('li', tabs).index(thisTab)); + + // Do not remove first tab + if (tabIndex != 0) { + // Go back to last tab if user is trying to close currently selected tab + if (tabs.tabs('option', 'selected') == tabIndex) { + // Get last selected tab from history + var order = $.cookie('xcat_tabindex_history').split(','); + if (order[1]) { + tabs.tabs('select', parseInt(order[1])); + } else { + tabs.tabs('select', 0); + } + } + + tabs.tabs('remove', tabIndex); + } + }); + } +}; + +/** + * Select a tab + * + * @param id Tab ID to select + */ +Tab.prototype.select = function(id) { + this.tab.tabs("select", "#" + id); +}; + +/** + * Remove a tab + * + * @param id Tab ID to remove + */ +Tab.prototype.remove = function(id) { + var selectorStr = 'a[href="\#' + id + '"]'; + var selectTab = $(selectorStr, this.tab).parent(); + var index = ($('li', this.tab).index(selectTab)); + this.tab.tabs("remove", index); +}; + +/** + * Table constructor + * + * @param tabId Tab ID + * @param tabName Tab name + */ +var Table = function(tableId) { + if ($('#' + tableId).length) { + this.tableId = tableId; + this.table = $('#' + tableId); + } else { + this.tableId = tableId; + this.table = null; + } +}; + +/** + * Initialize the table + * + * @param Headers Array of table headers + */ +Table.prototype.init = function(headers) { + // Create a table + this.table = $('
                                '); + var thead = $(''); + var headRow = $(''); + + // Append headers + for ( var i in headers) { + headRow.append('' + headers[i] + ''); + } + + thead.append(headRow); + this.table.append(thead); + + // Append table body + var tableBody = $(''); + this.table.append(tableBody); +}; + +/** + * Return the table object + * + * @return Object representing the table + */ +Table.prototype.object = function() { + return this.table; +}; + +/** + * Add a row to the table + * + * @param rowCont Array of table row contents + */ +Table.prototype.add = function(rowCont) { + // Create table row + var tableRow = $(''); + + // Create a column for each content + var tableCol; + for ( var i in rowCont) { + tableCol = $(''); + tableCol.append(rowCont[i]); + tableRow.append(tableCol); + } + + // Append table row to table + this.table.find('tbody').append(tableRow); +}; + +/** + * Add a footer to the table + * + * @param rowCont Array of table row contents + */ +Table.prototype.addFooter = function(rowCont) { + // Create table row + var tableFoot = $(''); + tableFoot.append(rowCont); + + // Append table row to table + this.table.append(tableFoot); +}; + +/** + * Remove a row from the table + */ +Table.prototype.remove = function(id) { + // To be continued +}; + +/** + * Datatable class constructor + * + * @param tabId Tab ID + * @param tabName Tab name + */ +var DataTable = function(tableId) { + this.dataTableId = tableId; + this.dataTable = null; +}; + +/** + * Initialize the datatable + * + * @param Headers Array of table headers + */ +DataTable.prototype.init = function(headers) { + // Create a table + this.dataTable = $('
                                '); + var thead = $(''); + var headRow = $(''); + + // Append headers + for ( var i in headers) { + headRow.append('' + headers[i] + ''); + } + + thead.append(headRow); + this.dataTable.append(thead); + + // Append table body + var tableBody = $(''); + this.dataTable.append(tableBody); +}; + +/** + * Return the datatable object + * + * @return Object representing the table + */ +DataTable.prototype.object = function() { + return this.dataTable; +}; + +/** + * Add a row to the datatable + * + * @param rowCont Array of table row contents + */ +DataTable.prototype.add = function(rowCont) { + // Create table row + var tableRow = $(''); + + // Create a column for each content + var tableCol; + for ( var i in rowCont) { + tableCol = $(''); + tableCol.append(rowCont[i]); + tableRow.append(tableCol); + } + + // Append table row to table + this.dataTable.find('tbody').append(tableRow); +}; + +/** + * Create status bar + * + * @param barId Status bar ID + */ +function createStatusBar(barId) { + // Do not change the background color or color! This is handled by the theme + // the user selects. + var statusBar = $('
                                ').css({ + 'margin-bottom': '5px', + 'min-height': '30px', + 'max-height': '150px', + 'overflow': 'auto' + }); + + // Create info icon + var icon = $('').css({ + 'display': 'inline-block', + 'margin': '10px 5px', + 'vertical-align': 'top' + }); + + // Create message section + var msg = $('
                                ').css({ + 'display': 'inline-block', + 'margin': '10px 0px', + 'width': '90%' + }); + + // Create hide button + var hide = $('').css({ + 'display': 'inline-block', + 'float': 'right', + 'cursor': 'pointer' + }).click(function() { + // Remove info box on-click + $(this).parent().hide(); + }); + + statusBar.append(icon); + statusBar.append(msg); + statusBar.append(hide); + return statusBar; +} + +/** + * Create info bar + * + * @param msg Info message + * @return Info bar + */ +function createInfoBar(msg) { + // Do not change the background color or color! This is handled by the theme + // the user selects. + var infoBar = $('
                                ').css({ + 'margin': '5px 0px' + }); + var icon = $('').css({ + 'display': 'inline-block', + 'margin': '10px 5px' + }); + var barMsg = $('

                                ' + msg + '

                                ').css({ + 'display': 'inline-block', + 'width': '90%' + }); + + infoBar.append(icon); + infoBar.append(barMsg); + return infoBar; +} + +/** + * Create warning bar + * + * @param msg Warning message + * @return Warning bar + */ +function createWarnBar(msg) { + var warnBar = $('
                                '); + var icon = $('').css({ + 'display': 'inline-block', + 'margin': '10px 5px' + }); + var barMsg = $('

                                ' + msg + '

                                ').css({ + 'display': 'inline-block', + 'width': '90%' + }); + + warnBar.append(icon); + warnBar.append(barMsg); + return warnBar; +} + +/** + * Create a loader + * + * @param loaderId Loader ID + */ +function createLoader(loaderId) { + var loader = $(''); + return loader; +} + +/** + * Create a button + * + * @param name Name of the button + */ +function createButton(name) { + var button = $('').button(); + return button; +} + +/** + * Create a menu + * + * @param items An array of items to go into the menu + * @return A division containing the menu + */ +function createMenu(items) { + var menu = $(''); + + // Loop through each item + for ( var i in items) { + // Append item to menu + var item = $('
                              15. '); + + // If it is a sub menu + if (items[i] instanceof Array) { + // 1st index = Sub menu title + item.append(items[i][0]); + // 2nd index = Sub menu + item.append(items[i][1]); + } else { + item.append(items[i]); + } + + menu.append(item); + } + + return menu; +} + +/** + * Initialize the page + */ +function initPage() { + // Load theme + var theme = $.cookie('xcat_theme'); + if (theme) { + switch (theme) { + case 'cupertino': + includeCss("css/themes/jquery-ui-cupertino.css"); + break; + case 'dark_hive': + includeCss("css/themes/jquery-ui-dark_hive.css"); + break; + case 'redmond': + includeCss("css/themes/jquery-ui-redmond.css"); + break; + case 'start': + includeCss("css/themes/jquery-ui-start.css"); + break; + case 'sunny': + includeCss("css/themes/jquery-ui-sunny.css"); + break; + case 'ui_dark': + includeCss("css/themes/jquery-ui-ui_darkness.css"); + break; + default: + includeCss("css/themes/jquery-ui-start.css"); + } + } else { + includeCss("css/themes/jquery-ui-start.css"); + } + + // Load jQuery stylesheets + includeCss("css/jquery.dataTables.css"); + includeCss("css/superfish.css"); + includeCss("css/jstree.css"); + includeCss("css/jquery.jqplot.css"); + + // Load custom stylesheet + includeCss("css/style.css"); + + // JQuery plugins + includeJs("js/jquery/jquery.dataTables.min.js"); + includeJs("js/jquery/jquery.form.min.js"); + includeJs("js/jquery/jquery.jeditable.min.js"); + includeJs("js/jquery/jquery.contextmenu.min.js"); + includeJs("js/jquery/superfish.min.js"); + includeJs("js/jquery/hoverIntent.min.js"); + includeJs("js/jquery/jquery.jstree.min.js"); + includeJs("js/jquery/tooltip.min.js"); + includeJs("js/jquery/jquery.serverBrowser.min.js"); + includeJs("js/jquery/jquery.jqplot.min.js"); + includeJs("js/jquery/jqplot.pieRenderer.min.js"); + includeJs("js/jquery/jqplot.dateAxisRenderer.min.js"); + includeJs("js/jquery/jquery.topzindex.min.js"); + + // Page plugins + includeJs("js/configure/configure.js"); + includeJs("js/monitor/monitor.js"); + includeJs("js/nodes/nodes.js"); + includeJs("js/provision/provision.js"); + + // Custom plugins + includeJs("js/custom/zvm.js"); + includeJs("js/custom/customUtils.js"); + + // Enable settings link + $('#xcat_settings').click(function() { + openSettings(); + }); + + // Set header to theme + var background = '', color = ''; + var theme = $.cookie('xcat_theme'); + if (theme) { + switch (theme) { + case 'cupertino': + background = '#3BAAE3'; + color = 'white'; + break; + case 'dark_hive': + background = '#0972A5'; + break; + case 'redmond': + background = '#F5F8F9'; + color = '#E17009'; + break; + case 'start': + background = '#6EAC2C'; + break; + case 'sunny': + background = 'white'; + color = '#0074C7'; + break; + case 'ui_dark': + background = '#F58400'; + break; + default: + background = '#6EAC2C'; + } + } else { + background = '#6EAC2C'; + } + + $('#header').addClass('ui-state-default'); + $('#header').css('border', '0px'); + + // Set theme to user span + $('#login_user').css('color', color); + + // Style for selected page + var style = { + 'background-color': background, + 'color': color + }; + + // Get the page being loaded + var url = window.location.pathname; + var page = url.replace('/xcat/', ''); + var headers = $('#header ul li a'); + + // Show the page + $("#content").children().remove(); + if (page == 'configure.php') { + includeJs("js/configure/update.js"); + includeJs("js/configure/service.js"); + includeJs("js/configure/users.js"); + includeJs("js/configure/files.js"); + headers.eq(1).css(style); + loadConfigPage(); + } else if (page == 'provision.php') { + includeJs("js/provision/images.js"); + headers.eq(2).css(style); + loadProvisionPage(); + } else if (page == 'help.php') { + includeJs("js/help/help.js"); + headers.eq(4).css(style); + loadHelpPage(); + } else { + // Load nodes page by default + includeJs("js/nodes/nodeset.js"); + includeJs("js/nodes/rnetboot.js"); + includeJs("js/nodes/updatenode.js"); + includeJs("js/nodes/rscan.js"); + headers.eq(0).css(style); + loadNodesPage(); + } +} + +/** + * Include javascript file in + * + * @param file File to include + */ +function includeJs(file) { + var script = $("head script[src='" + file + "']"); + + // If does not contain the javascript + if (!script.length) { + // Append the javascript to + var script = $(''); + script.attr( { + type : 'text/javascript', + src : file + }); + + $('head').append(script); + } +} + +/** + * Include CSS link in + * + * @param file File to include + */ +function includeCss(file) { + var link = $("head link[href='" + file + "']"); + + // If does not contain the link + if (!link.length) { + // Append the CSS link to + var link = $(''); + link.attr( { + type : 'text/css', + rel : 'stylesheet', + href : file + }); + + $('head').append(link); + } +} + +/** + * Write ajax response to a paragraph + * + * @param rsp Ajax response + * @param pattern Pattern to replace with a break + * @return Paragraph containing ajax response + */ +function writeRsp(rsp, pattern) { + // Create paragraph to hold ajax response + var prg = $('
                                ');
                                +
                                +    for ( var i in rsp) {
                                +        if (rsp[i]) {
                                +            // Create regular expression for given pattern
                                +            // Replace pattern with break
                                +            if (pattern) {
                                +                rsp[i] = rsp[i].replace(new RegExp(pattern, 'g'), '
                                '); + prg.append(rsp[i]); + } else { + prg.append(rsp[i]); + prg.append('
                                '); + } + } + } + + return prg; +} + +/** + * Open a dialog and show given message + * + * @param type Type of dialog, i.e. warn or info + * @param msg Message to show + */ +function openDialog(type, msg) { + var msgDialog = $('
                                '); + var title = ""; + if (type == "warn") { + // Create warning message + msgDialog.append(createWarnBar(msg)); + title = "Warning"; + } else { + // Create info message + msgDialog.append(createInfoBar(msg)); + title = "Info"; + } + + // Open dialog + msgDialog.dialog({ + title: title, + modal: true, + close: function(){ + $(this).remove(); + }, + width: 500, + buttons: { + "Ok": function(){ + $(this).dialog("close"); + } + } + }); +} + +/** + * Create an iframe to hold the output of an xCAT command + * + * @param src The URL of the document to show in the iframe + * @return Info box containing the iframe + */ +function createIFrame(src) { + // Put an iframe inside an info box + var infoBar = $('
                                ').css({ + 'margin-bottom': '5px' + }); + + // Create info and close icons + var icon = $('').css({ + 'display': 'inline-block', + 'margin': '10px 5px' + }); + var close = $('').css({ + 'display': 'inline-block', + 'float': 'right', + 'margin': '10px 5px' + }).click(function() { + // Remove info box on-click + $(this).parent().remove(); + }); + + var iframe = $('').attr('src', src).css({ + 'display': 'block', + 'border': '0px', + 'margin': '10px', + 'width': '100%' + }); + + var loader = createLoader('iLoader').css({ + 'display': 'block', + 'margin': '10px 0px' + }); + + infoBar.append(icon); + infoBar.append($('
                                ').append(loader, iframe)); + infoBar.append(close); + + // Remove loader when done + iframe.load(function() { + loader.remove(); + }); + + return infoBar; +} + + +/** + * Open dialog to set xCAT UI settings + */ +function openSettings() { + // Create form to add node range + var dialog = $('
                                '); + var info = createInfoBar('Select from the following options'); + dialog.append(info); + + var style = { + 'color': 'blue', + 'cursor': 'pointer', + 'padding': '5px' + }; + + var changeThemeOption = $('
                                Change xCAT theme
                                ').css(style); + dialog.append(changeThemeOption); + + var changePasswordOption = $('
                                Change password
                                ').css(style); + dialog.append(changePasswordOption); + + // Open form as a dialog + dialog.dialog({ + modal: true, + close: function(){ + $(this).remove(); + }, + title: 'Settings', + width: 400, + buttons: { + "Cancel": function(){ + $(this).dialog("close"); + } + } + }); + + // Bind to click event + changeThemeOption.click(function() { + dialog.dialog("close"); + changeTheme(); + }); + + changePasswordOption.click(function() { + dialog.dialog("close"); + changePassword(); + }); +} + +/** + * Open dialog to change xCAT theme + */ +function changeTheme() { + // Create form to add node range + var dialog = $('
                                '); + var info = createInfoBar('Select the xCAT theme you desire'); + dialog.append(info); + + // Create select drop down for themes + var oList = $('
                                  '); + oList.append($('
                                1. Cupertino
                                2. ')); + oList.append($('
                                3. Dark Hive
                                4. ')); + oList.append($('
                                5. Redmond
                                6. ')); + oList.append($('
                                7. Start (default)
                                8. ')); + oList.append($('
                                9. Sunny
                                10. ')); + oList.append($('
                                11. UI Darkness
                                12. ')); + dialog.append(oList); + + if ($.cookie('xcat_theme')) { + // Select theme + oList.find('input[value="' + $.cookie('xcat_theme') + '"]').attr('checked', true); + } else { + oList.find('input[value="start"]').attr('checked', true); + } + + // Open form as a dialog + dialog.dialog({ + modal: true, + close: function(){ + $(this).remove(); + }, + title: 'xCAT Theme', + width: 400, + buttons: { + "Ok": function(){ + // Save selected theme + var theme = $(this).find('input[name="theme"]:checked').val(); + $.cookie('xcat_theme', theme); // Do not expire cookie, keep it as long as possible + + // Show instructions to apply theme + $(this).empty(); + var info = createInfoBar('You will need to reload this page in order for changes to take effect'); + $(this).append(info); + + // Only show close button + $(this).dialog("option", "buttons", { + "Close" : function() { + $(this).dialog( "close" ); + } + }); + }, + "Cancel": function(){ + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Open dialog to change user password + */ +function changePassword() { + // Create form to add node range + var dialog = $('
                                  '); + var info = createInfoBar('Change your password'); + dialog.append(info); + + dialog.append('
                                  '); + dialog.append('
                                  '); + + // Open form as a dialog + dialog.dialog({ + modal: true, + close: function(){ + $(this).remove(); + }, + title: 'Change Password', + width: 400, + buttons: { + "Ok": function(){ + // Remove any warning messages + $(this).find('.ui-state-error').remove(); + + var errorMessage = ""; + + // Check each input is provided + $('#changePassword input').each(function() { + if (!$(this).val()) { + errorMessage = "Please provide a value for each missing input!"; + } + }); + + // Do not continue if error found + if (errorMessage) { + dialog.prepend(createWarnBar(errorMessage)); + return; + } + + // Check new and confirm passwords match + var user = $.cookie('xcat_username'); + var newPassword = $('#changePassword input[name="newPassword"]').val(); + var confirmPassword = $('#changePassword input[name="confirmPassword"]').val(); + if (newPassword != confirmPassword) { + dialog.prepend(createWarnBar("Please confirm new password!")); + return; + } + + // Change dialog buttons + $('#changePassword').dialog('option', 'buttons', { + 'Close':function(){ + $('#changePassword').dialog('destroy').remove(); + } + }); + + // Send request to change password + var url = window.location.pathname; + var page = url.replace('/xcat/', ''); + var url = 'lib/cmd.php'; + // Service portal does not have access to cmd.php + if (page == 'service.php') + url = 'lib/srv_cmd.php'; + $.ajax( { + url : url, + dataType : 'json', + data : { + cmd : 'webrun', + tgt : '', + args : 'passwd;' + user + ';' + newPassword, + msg : '' + }, + + success : function (data) { + // Show response message + var rspMessage = ""; + for (var i in data.rsp) + rspMessage += data.rsp[i] + "
                                  "; + + $('#changePassword').prepend(createInfoBar(rspMessage)); + } + }); + }, + "Cancel": function(){ + $(this).dialog( "close" ); + } + } + }); +} + +/** + * Adjust datatable column size + * + * @param tableId Table ID + */ +function adjustColumnSize(tableId) { + var dTable = $('#' + tableId).dataTable(); + dTable.fnAdjustColumnSizing(); +} + +/** + * Set menu theme + * + * @param menu Menu object + */ +function setMenu2Theme(menu) { + // On hover + var background = '', color = ''; + var theme = $.cookie('xcat_theme'); + if (theme) { + switch (theme) { + case 'cupertino': + background = '#3BAAE3'; + color = 'white'; + break; + case 'dark_hive': + background = '#0972A5'; + break; + case 'redmond': + background = '#F5F8F9'; + color = '#E17009'; + break; + case 'start': + background = '#6EAC2C'; + break; + case 'sunny': + background = 'white'; + color = '#0074C7'; + break; + case 'ui_dark': + background = '#F58400'; + break; + default: + background = '#6EAC2C'; + } + } else { + background = '#6EAC2C'; + } + + menu.css('background', background); + menu.find('a:eq(0)').css('color', color); +} + +/** + * Set menu back to normal before applying theme + * + * @param menu Menu object + */ +function setMenu2Normal(menu) { + // Change back to normal + menu.css('background', ''); + menu.find('a:eq(0)').css('color', ''); +} + +/** + * Get nodes that are checked in a given datatable + * + * @param datatableId The datatable ID + * @return Nodes that were checked + */ +function getNodesChecked(datatableId) { + var tgts = ''; + + // Get nodes that were checked + var nodes = $('#' + datatableId + ' 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; +} + +/** + * Check if return message contains errors + * + * @param msg Return message + * @return 0 If return message contains no errors + * -1 If return message contains errors + */ +function containErrors(msg) { + if (msg.indexOf('Failed') > -1 || msg.indexOf('Error') > -1) { + return -1; + } else { + return 0; + } +} + +/** + * Check if a value is an integer + * + * @param value Value to be checked + * @returns true If value is an integer + false If value is not an integer + */ +function isInteger(value){ + if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) { + return true; + } else { + return false; + } +} + +/** + * Remove html encoding from php htmlentities() conversion + * + * @param encodedString + */ +function decodeHTML(encodedString) { + var txt = document.createElement("textarea"); + txt.innerHTML = encodedString; + return txt.value; +} + +/** + * Remove html encoding from rsp.data array and rsp.msg + * + * @param encodedData from server response + */ +function decodeRsp(encodedData) { + /* response data has rsp and msg. msg is a string. + rsp is a string, or array of strings or array of arrays with strings*/ + if ( (typeof encodedData.rsp != "undefined") && (encodedData.rsp.length > 0) ) { + if (encodedData.rsp.constructor === Array) { + for (var i in encodedData.rsp) { + if (encodedData.rsp[i].constructor === Array) { + for (var j in encodedData.rsp[i]) { + encodedData.rsp[i][j] = decodeHTML(encodedData.rsp[i][j]); + } + } else { + encodedData.rsp[i] = decodeHTML(encodedData.rsp[i]); + } + } + } else { + encodedData.rsp = decodeHTML(encodedData.rsp); + } + } + /* msg is a string */ + if ( (typeof encodedData.msg != "undefined") && (encodedData.msg.length > 0) ){ + encodedData.msg = decodeHTML(encodedData.msg); + } + return encodedData; +} diff --git a/xCAT-UI/lib/cmd.php b/xCAT-UI/lib/cmd.php index f63f83000..db9a3a23b 100644 --- a/xCAT-UI/lib/cmd.php +++ b/xCAT-UI/lib/cmd.php @@ -1,225 +1,241 @@ -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; - } - - if ($data->data->desc) { - $cont = $data->data->desc . ": " . $cont; - } - - $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; -} +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; + } + + if ($data->data->desc) { + $cont = $data->data->desc . ": " . $cont; + } + + $cont = str_replace(":|:", "\n", $cont); + array_push($rsp, "$node: $cont"); + } else if (strlen("$data") > 2) { + $data = str_replace(":|:", "\n", $data); + array_push($rsp, "$data"); + } + } + } + } + // Remove any HTML that could be used for XSS attacks + foreach ($rsp as $key => &$value) { + $whatami = gettype($value); + if ("string" != $whatami) { + //echo "found a non string in rsp array \n"; + foreach ($value as $key2 => $value2){ + //echo "Key2:$key2 Value2 type:",gettype($value2)," value2 data: $value2 \n"; + $value[$key2] = htmlentities($value2, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + } + } else { + //echo "Key:$key Value type:",gettype($value)," value data: $value \n"; + $rsp[$key] = htmlentities($value, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + //echo "New value: $rsp[$key] \n"; + } + } + $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + + // 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_cmd.php b/xCAT-UI/lib/srv_cmd.php index c1b226369..ecb4fc1a4 100644 --- a/xCAT-UI/lib/srv_cmd.php +++ b/xCAT-UI/lib/srv_cmd.php @@ -1,190 +1,206 @@ -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; -} +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"); + } + } + } + } + // Remove any HTML that could be used for XSS attacks + foreach ($rsp as $key => &$value) { + $whatami = gettype($value); + if ("string" != $whatami) { + //echo "found a non string in rsp array \n"; + foreach ($value as $key2 => $value2){ + //echo "Key2:$key2 Value2 type:",gettype($value2)," value2 data: $value2 \n"; + $value[$key2] = htmlentities($value2, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + } + } else { + //echo "Key:$key Value type:",gettype($value)," value data: $value \n"; + $rsp[$key] = htmlentities($value, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + //echo "New value: $rsp[$key] \n"; + } + } + $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + + // 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/systemcmd.php b/xCAT-UI/lib/systemcmd.php index 7990aa035..94bbc4444 100644 --- a/xCAT-UI/lib/systemcmd.php +++ b/xCAT-UI/lib/systemcmd.php @@ -1,36 +1,39 @@ -Please login before continuing!"); - exit; -} - -if (isset($_GET["cmd"])) { - // HTTP GET requests - $cmd = $_GET["cmd"]; - $msg = NULL; - $ret = ""; - - if (isset($_GET["msg"])) { - $msg = $_GET["msg"]; - } - - if ($cmd == "ostype") { - $ret = strtolower(PHP_OS); - } else { - $ret = shell_exec($cmd); - } - - echo json_encode(array("rsp"=>$ret, "msg" => $msg)); -} +Please login before continuing!"); + exit; +} + +if (isset($_GET["cmd"])) { + // HTTP GET requests + $cmd = $_GET["cmd"]; + $msg = NULL; + $ret = ""; + + if (isset($_GET["msg"])) { + $msg = $_GET["msg"]; + } + + if ($cmd == "ostype") { + $ret = strtolower(PHP_OS); + } else { + $ret = shell_exec($cmd); + } + + // Remove any HTML that could be used for XSS attacks + $ret = htmlentities($ret, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + echo json_encode(array("rsp"=>$ret, "msg" => $msg)); +} ?> \ No newline at end of file diff --git a/xCAT-UI/lib/zCmd.php b/xCAT-UI/lib/zCmd.php index c2a21eebf..c77f4b5fe 100644 --- a/xCAT-UI/lib/zCmd.php +++ b/xCAT-UI/lib/zCmd.php @@ -1,142 +1,159 @@ -children() as $child) { - foreach ($child->children() as $data) { - $data = str_replace(":|:", "\n", $data); - array_push($rsp, "$data"); - } - } - } - - // Create virtual server - else if (strncasecmp($cmd, "mkvm", 4) == 0) { - // Directory /var/tmp permissions = 777 - // You can write anything to that directory - $userEntry = "/var/tmp/$tgt.txt"; - $handle = fopen($userEntry, 'w') or die("Cannot open $userEntry"); - fwrite($handle, $att); - fclose($handle); - - // CLI command: mkvm gpok3 /tmp/gpok3.txt - // Create user entry - array_unshift($arr, $userEntry); - $xml = docmd($cmd, $tgt, $arr, NULL); - foreach ($xml->children() as $child) { - foreach ($child->children() as $data) { - $data = str_replace(":|:", "\n", $data); - array_push($rsp, "$data"); - } - } - } - - // Run shell script - // This is a typical command used by all platforms. It is put here because - // most of the code needed are already here - else if (strncasecmp($cmd, "xdsh", 4) == 0) { - // Directory /var/tmp permissions = 777 - // You can write anything to that directory - $msgArgs = explode(";", $msg); - $inst = str_replace("out=scriptStatusBar", "", $msgArgs[0]); - $script = "/var/tmp/script$inst.sh"; - - // Write to file - $handle = fopen($script, 'w') or die("Cannot open $script"); - fwrite($handle, $att); - fclose($handle); - - // Change it to executable - chmod($script, 0777); - - // CLI command: xdsh gpok3 -e /var/tmp/gpok3.sh - // Create user entry - array_push($arr, $script); - $xml = docmd($cmd, $tgt, $arr, NULL); - foreach ($xml->children() as $child) { - foreach ($child->children() as $data) { - $data = str_replace(":|:", "\n", $data); - array_push($rsp, "$data"); - } - } - - // Remove this file - unlink($script); - } - - // Reply in the form of JSON - $rtn = array("rsp" => $rsp, "msg" => $msg); - echo json_encode($rtn); -} +children() as $child) { + foreach ($child->children() as $data) { + $data = str_replace(":|:", "\n", $data); + array_push($rsp, "$data"); + } + } + } + + // Create virtual server + else if (strncasecmp($cmd, "mkvm", 4) == 0) { + // Directory /var/tmp permissions = 777 + // You can write anything to that directory + $userEntry = "/var/tmp/$tgt.txt"; + $handle = fopen($userEntry, 'w') or die("Cannot open $userEntry"); + fwrite($handle, $att); + fclose($handle); + + // CLI command: mkvm gpok3 /tmp/gpok3.txt + // Create user entry + array_unshift($arr, $userEntry); + $xml = docmd($cmd, $tgt, $arr, NULL); + foreach ($xml->children() as $child) { + foreach ($child->children() as $data) { + $data = str_replace(":|:", "\n", $data); + array_push($rsp, "$data"); + } + } + } + + // Run shell script + // This is a typical command used by all platforms. It is put here because + // most of the code needed are already here + else if (strncasecmp($cmd, "xdsh", 4) == 0) { + // Directory /var/tmp permissions = 777 + // You can write anything to that directory + $msgArgs = explode(";", $msg); + $inst = str_replace("out=scriptStatusBar", "", $msgArgs[0]); + $script = "/var/tmp/script$inst.sh"; + + // Write to file + $handle = fopen($script, 'w') or die("Cannot open $script"); + fwrite($handle, $att); + fclose($handle); + + // Change it to executable + chmod($script, 0777); + + // CLI command: xdsh gpok3 -e /var/tmp/gpok3.sh + // Create user entry + array_push($arr, $script); + $xml = docmd($cmd, $tgt, $arr, NULL); + foreach ($xml->children() as $child) { + foreach ($child->children() as $data) { + $data = str_replace(":|:", "\n", $data); + array_push($rsp, "$data"); + } + } + + // Remove this file + unlink($script); + } + + // Remove any HTML that could be used for XSS attacks + foreach ($rsp as $key => &$value) { + $whatami = gettype($value); + if ("string" != $whatami) { + //echo "found a non string in rsp array \n"; + foreach ($value as $key2 => $value2){ + //echo "Key2:$key2 Value2 type:",gettype($value2)," value2 data: $value2 \n"; + $value[$key2] = htmlentities($value2, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + } + } else { + //echo "Key:$key Value type:",gettype($value)," value data: $value \n"; + $rsp[$key] = htmlentities($value, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + //echo "New value: $rsp[$key] \n"; + } + } + $msg = htmlentities($msg, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + + // Reply in the form of JSON + $rtn = array("rsp" => $rsp, "msg" => $msg); + echo json_encode($rtn); +} ?> \ No newline at end of file diff --git a/xCAT-client/bin/verifynode b/xCAT-client/bin/verifynode index a769edb33..66c29ffdb 100644 --- a/xCAT-client/bin/verifynode +++ b/xCAT-client/bin/verifynode @@ -44,6 +44,7 @@ use xCAT::zvmUtils; my $version = "1"; my $comments = ''; # Comments for the IVP run +my $dataFile = ''; # Input data file my $decode = ''; # String specified by the --decode operand. my $disable = ''; # Disable scheduled IVP from running. my $displayHelp = 0; # Display help information @@ -56,6 +57,8 @@ my %hosts; # Information on host nodes known by xCAT my $id = ''; # Id of the IVP run my %ignored; # List of ignored messages my $ignoreCnt = 0; # Number of times we ignored a message +my $issueCmdOverIUCV = ''; # Issue a command to a node over IUCV +my $issueCmdToNode = ''; # Issue a command to a node using IUCV or SSH my %localIPs; # Hash of the Local IP addresses for the xCAT MN system my $logDir = '/var/log/xcat/ivp'; # Log location my $logFile = ''; # Log file name and location @@ -63,7 +66,7 @@ my $logFileHandle; # File handle for the log file. my @ivpSummary; # Summary output lines for an IVP run. my $locApplSystemRole = '/var/lib/sspmod/appliance_system_role'; my %mnInfo; # Managed node environment information -my %msgsToIgnore; # Hash of messages to ignore +my %msgsToIgnore; # Hash of messages to ignore my $needToFinishLogFile = 0; # If 1 then finishLogFile() needs to be called my $nodeName = ''; # Name of node to be verified my $notify = 0; # Notify a user @@ -112,6 +115,14 @@ my %verifySets = ( [ 'Encoding a string', 'encodeDecodeString()', ], + '$issueCmdOverIUCV ne \'\'' => + [ 'Issue a command to a node using IUCV', + 'cmdOnVM( \'onlyIUCV\' )', + ], + '$issueCmdToNode ne \'\'' => + [ 'Issue a command to a node using IUCV or SSH', + 'cmdOnVM( \'either\' )', + ], '$remove' => [ 'Remove an automated periodic IVP', 'removeIVP( $id )', @@ -159,7 +170,7 @@ my %verifySets = ( 'verifyPower( $nodeName )', 'verifyAccess( $nodeName )', 'getDistro( $nodeName )', - 'verifyService($nodeOrIP, "cloud-config,2,3,4,5 cloud-final,2,3,4,5 cloud-init,2,3,4,5 cloud-init-local,2,3,4,5")', + 'verifyService($nodeName, "cloud-config,2,3,4,5 cloud-final,2,3,4,5 cloud-init,2,3,4,5 cloud-init-local,2,3,4,5")', 'showCILevel()', ], '$verifyXcatconf4z' => @@ -167,7 +178,7 @@ my %verifySets = ( 'verifyPower( $nodeName )', 'verifyAccess( $nodeName )', 'getDistro( $nodeName )', - 'verifyXcatconf4z()', + 'verifyXcatconf4z( $nodeName )', ], '$test' => [ 'Script test functon.', @@ -193,6 +204,14 @@ my $usage_string = "Usage:\n --capturereqs Verify that node meets system capture requirements for OpenStack. + --cmdoveriucv + Issue a command to a node using IUCV. + Specify a period for when combining this + option with the --file option. + --cmdtonode Issue a command to a node using IUCV or SSH + if IUCV is not available. + Specify a period for when combining this + option with the --file option. -c | --cloudinit Verify that node has cloud-init installed. --comments @@ -214,6 +233,9 @@ my $usage_string = "Usage:\n string from the zvmivp table. The must be an ASCII string. This function does not support encoding a UTF-8 character string. + --file File location containing additional input. + When used with the --cmdoveriucv or --cmdtonode + operands, this file contains the command to issue. --fullivp Run the full end-to-end IVP. This verification checks the compute node and builds @@ -380,6 +402,127 @@ sub checkForDefault { } +#------------------------------------------------------- + +=head3 cmdOnVM + + Description : Send a command to a node and show the result. + Arguments : Target function, either 'onlyIUCV' or 'either'. + Returns : Return code: + 0 - Normal Linux success + 255 - Unable to SSH to system + non-zero - command error + Output from the command or a error string on an SSH failure. + Example : $rc = cmdOnVM( 'onlyIUCV' ); + $rc = cmdOnVM( 'either' ); + +=cut + +#------------------------------------------------------- +sub cmdOnVM { + my ( $targetFunc ) = @_; + my $cmd = ''; + my $hcp = ''; + my @lines; + my $rc = 0; + my $out = ''; + my $sudo; + my $user; + my $userid = ''; + + # Get the command to issue. + if ( $targetFunc eq 'onlyIUCV' ) { + if ( $issueCmdOverIUCV ne '.' ) { + $cmd = $issueCmdOverIUCV; + } + } else { + if ( $issueCmdToNode ne '.' ) { + $cmd = $issueCmdToNode; + } + } + + # Use the data file if it was specified. + if ( $dataFile ne '' ) { + if ( -e $dataFile ) { + open my $handle, '<', $dataFile; + chomp( @lines = <$handle> ); + close $handle; + if ( $lines[0] ne '' ) { + $cmd = $lines[0]; + } else { + logResponse( 'DF', 'GENERIC_RESPONSE', "$dataFile does not have anything in the first line."); + goto FINISH_cmdUsingIUCV; + } + } else { + logResponse( 'DF', 'GENERIC_RESPONSE', "$dataFile does not exist."); + goto FINISH_cmdUsingIUCV; + } + } + + # Verify that we have a command to issue. + if ( $cmd eq '' ) { + logResponse( 'DF', 'GENERIC_RESPONSE', "A command to issue was not specified."); + goto FINISH_cmdUsingIUCV; + } + + ($user, $sudo) = xCAT::zvmUtils->getSudoer(); + + # Get the required properties (hcp, userid, user) from the node + $out = `/opt/xcat/bin/lsdef $nodeName -i hcp,userid`; + $rc = $?; + if ( $rc eq 0 ) { + my $fndNode = 0; + @lines = split( '\n', $out ); + my $host = ''; + foreach my $line ( @lines ) { + $line =~ s/^\s+|\s+$//g; # trim blanks from both ends of the string + if ( $line =~ /Object name:/ ) { + $fndNode = 1; + next; + } elsif ( $line =~ /hcp\=/ ) { + ($hcp) = $line =~ m/hcp\=(.*)/; + next; + } elsif ( $line =~ /userid\=/ ) { + ($userid) = $line =~ m/userid\=(.*)/; + next; + } + } + if ( $fndNode != 1 ) { + logResponse( 'DF', 'GENERIC_RESPONSE', "'$nodeName' is not an xCAT node." ); + goto FINISH_cmdUsingIUCV; + } + } else { + $rc = logResponse( 'DFS', 'GNRL01', "$cmd", $rc, $out ); + goto FINISH_cmdUsingIUCV; + } + + # Send the command through IUCV + logResponse( 'DF', '*NONFORMATTED*', "\n**************************\nData for the function call\n**************************" ); + logResponse( 'DF', '*NONFORMATTED*', " Node: $nodeName" ); + if ( $targetFunc eq 'onlyIUCV' ) { + logResponse( 'DF', '*NONFORMATTED*', "z/VM userid: $userid" ); + logResponse( 'DF', '*NONFORMATTED*', " HCP: $hcp" ); + logResponse( 'DF', '*NONFORMATTED*', " User: $user" ); + logResponse( 'DF', '*NONFORMATTED*', " Function: xCAT::zvmUtils->execcmdthroughIUCV" ); + } else { + logResponse( 'DF', '*NONFORMATTED*', " User: $user" ); + logResponse( 'DF', '*NONFORMATTED*', " Function: xCAT::zvmUtils->execcmdonVM" ); + } + logResponse( 'DF', '*NONFORMATTED*', " Cmd: $cmd" ); + + logResponse( 'DF', '*NONFORMATTED*', "\n*********************\nInvoking the function\n*********************" ); + if ( $targetFunc eq 'onlyIUCV' ) { + $out = xCAT::zvmUtils->execcmdthroughIUCV( $user, $hcp, $userid, $cmd ); + } else { + $out = xCAT::zvmUtils->execcmdonVM( $user, $nodeName, $cmd ); + } + logResponse( 'DF', '*NONFORMATTED*', "\n******\nResult\n******\n$out" ); + +FINISH_cmdUsingIUCV: + return $rc; +} + + #------------------------------------------------------- =head3 driveCronList @@ -2590,7 +2733,7 @@ FINISH_verifyService: Description : Verify xcatconf4z is properly installed and is the correct version. - Arguments : None + Arguments : Node name or IP address Returns : 0 - No error non-zero - Terminating error detected. Example : $rc = verifyXcatconf4z(); @@ -2695,10 +2838,13 @@ if (!GetOptions( 'disable' => \$disable, 'enable' => \$enable, 'encode=s' => \$encode, + 'file=s' => \$dataFile, 'fullivp' => \$runFullIVP, 'h|help' => \$displayHelp, 'i|id=s' => \$id, 'ignore=s' => \$ignoreOpt, + 'cmdoveriucv=s' => \$issueCmdOverIUCV, + 'cmdtonode=s' => \$issueCmdToNode, 'n|node=s' => \$nodeName, 'notify' => \$notifyOnErrorOrWarning, 'openstackuser=s' => \$openstackUser, @@ -2810,9 +2956,7 @@ if ( $decode ne '' or $remove or $schedule ne '' ) { # IVP runs do not need the node. -} elsif ( $nodeName ne '' ) { - $nodeName = lc( $nodeName ); -} else { +} elsif ( $nodeName eq '' ) { $rc = logResponse( 'DFS', 'OPER01', '-n or --node' ); goto FINISH_main; } diff --git a/xCAT-server/lib/xcat/plugins/zvm.pm b/xCAT-server/lib/xcat/plugins/zvm.pm index 1743f69bd..6624fe7e1 100644 --- a/xCAT-server/lib/xcat/plugins/zvm.pm +++ b/xCAT-server/lib/xcat/plugins/zvm.pm @@ -742,7 +742,7 @@ sub process_request { Arguments : Node to remove Upstream instance ID (Optional) Upstream request ID (Optional) - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : removeVM($callback, $node); =cut @@ -776,6 +776,7 @@ sub removeVM { xCAT::zvmUtils->printSyslog("sudoer:$::SUDOER zHCP:$hcp sudo:$::SUDO"); my $out; + my $outmsg; my $requestId = "NoUpstreamRequestID"; # Default is still visible in the log my $objectId = "NoUpstreamObjectID"; # Default is still visible in the log @@ -796,6 +797,10 @@ sub removeVM { # its resources. First, get any vswitches in directory. xCAT::zvmUtils->printSyslog("Calling getVswitchIdsFromDirectory $::SUDOER, $hcp, $userId"); my @vswitch = xCAT::zvmUtils->getVswitchIdsFromDirectory( $::SUDOER, $hcp, $userId); + if (xCAT::zvmUtils->checkOutput( $vswitch[0] ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$vswitch[0]" ); + return; + } my %vswitchhash; # For each vswitch revoke the userid vswitch authority foreach (@vswitch) { @@ -864,7 +869,14 @@ sub removeVM { if (!(length $_)) {next;} $pool = xCAT::zvmUtils->replaceStr( $_, ".conf", "" ); - @luns = split("\n", `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_" | egrep -a -i $node`); + $out = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$_\"", $hcp, "removeVM", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i $node`; + @luns = split("\n", $out); foreach (@luns) { if (!(length $_)) {next;} # Update entry: status,wwpn,lun,size,range,owner,channel,tag @@ -916,7 +928,7 @@ sub removeVM { Description : Change a virtual machine's configuration Arguments : Node Option - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : changeVM($callback, $node, $args); =cut @@ -964,6 +976,11 @@ sub changeVM { # Output string my $out = ""; + my $outmsg; + my $device = 0; + my $newlinkcall = 0; + my $rc = 0; + my $vdev; # add3390 [disk pool] [device address] [size] [mode] [read password (optional)] [write password (optional)] [multi password (optional)] [fstype (optional)] if ( $args->[0] eq "--add3390" ) { @@ -1041,56 +1058,103 @@ sub changeVM { if ( $fstype && !$error ) { # Format the disk before making it active. # link the disk - my $retry = 3; - my $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); - while ( $retry > 0 ) { - # wait 2 seconds for disk creation complete - sleep(2); - $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`; - $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + # Check if zhcp has the new routine to link and online the disk + $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/linkdiskandbringonline $userId $addr $mode"`; - if ($error) { - $retry -= 1; - $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); + $rc = $? >> 8; + if ($rc == 255) { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unable to communicate with zHCP agent: $hcp" ); + $error = 1; + } elsif ( $rc > 0 && $rc != 127 ) { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM()Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" ); + $error = 1; + } elsif ( $rc ==0 ) { + $newlinkcall = 1; + if ($out =~ m/Success:/i){ + # sample output=>linkdiskandbringonline maint start time: 2017-03-03-16:20:48.011 + # Success: Userid maint vdev 193 linked at ad35 device name dasdh + # linkdiskandbringonline exit time: 2017-03-03-16:20:52.150 + $out = `echo "$out" | egrep -a -i "Success:"`; + my @info = split( ' ', $out ); + $device = "/dev/" . $info[10]; } else { - last; + xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to linkdiskandbringonline: $out" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Error occurred in call to linkdiskandbringonline: $out" ); + $error = 1; } - } + } else { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Could not find zhcp linkdiskandbringonline, using old code path." ); + my $retry = 3; + $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); + while ( $retry > 0 ) { + # wait 2 seconds for disk creation complete + sleep(2); + $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`; + $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; - # make the disk online and get it's device name - my $device = 0; - if ( !$error ) { - $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`; - $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev ); - my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices | grep -a 0.0.$vdev"`; - chomp( $select ); - # A sample entry: - # 0.0.0101(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 600840 blocks, 2347 MB - if ( $select ) { - my @info = split( ' ', $select ); - $device = "/dev/" . $info[6]; + if ($error) { + $retry -= 1; + $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); + } else { + last; + } + } + + # make the disk online and get it's device name + if ( !$error ) { + $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`; + $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev ); + my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat /proc/dasd/devices\"", $hcp, "changeVM", $select, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + $error = 1; + } else { + $select = `echo "$select" | egrep -a -i "0.0.$vdev"`; + chomp( $select ); + # A sample entry: + # 0.0.0101(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 600840 blocks, 2347 MB + if ( $select ) { + my @info = split( ' ', $select ); + $device = "/dev/" . $info[6]; + } + $error = !$device; + } } - $error = !$device; } # format the disk if ( !$error ) { $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/dasdfmt -y -b 4096 -d cdl -f $device 2>&1"`; $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during dasdfmt $device. Output: $out" ); + } } if ( !$error ) { $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/fdasd -a $device 2>&1"`; $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during fdasd $device. Output: $out" ); + } } if ( !$error ) { $device .= '1'; if ( $fstype =~ m/xfs/i ) { $out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs.xfs $device 2>&1"`; $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during mkfs.xfs $device. Output: $out" ); + } } else { $out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs -t $fstype $device 2>&1"`; $error = !($out =~ m/done/); - } + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during mkfs $fstype $device. Output: $out" ); + } + } } if ( $error ) { xCAT::zvmUtils->printSyslog("$out"); @@ -1099,20 +1163,46 @@ sub changeVM { $out = ""; } - xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev ); - `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`; - xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev"); + # offline and detach disk using new call so that zhcp records are updated + if ( $newlinkcall == 1 ){ + $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/offlinediskanddetach $userId $addr"`; + $rc = $?; + + $rc = $? >> 8; + if ( $rc == 255 ) { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unable to communicate with zHCP agent: $hcp" ); + $error = 1; + } + if ($out =~ m/Success:/i){ + # sample output=>offlinediskanddetach maint start time: 2017-03-03-16:20:48.011 + # Success: Userid maint vdev 193 unlinked + # offlinediskanddetach exit time: 2017-03-03-16:20:52.150 + xCAT::zvmUtils->printSyslog("$out"); + } else { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" ); + $error = 1; + } + # Use old code to disable and detach + } else { + xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev ); + `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`; + xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev"); + } } - # Add to active configuration - $out .= "Adding 3390 disk for $node as $addr ... Done"; - my $power = `/opt/xcat/bin/rpower $node stat`; - if ($power =~ m/: on/i) { - $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`; - xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode"); - } + if ( !$error ) { + # Add to active configuration + $out .= "Adding 3390 disk for $node as $addr ... Done"; + my $power = `/opt/xcat/bin/rpower $node stat`; + if ($power =~ m/: on/i) { + $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`; + xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode"); + } - $out = xCAT::zvmUtils->appendHostname( $node, $out ); + $out = xCAT::zvmUtils->appendHostname( $node, $out ); + } } # add3390active [device address] [mode] @@ -1198,38 +1288,79 @@ sub changeVM { $error = 1; } + my $device = 0; + my $newlinkcall = 0; + my $rc = 0; + my $vdev; + if ( $fstype && !$error ) { # Format the disk before making it active. # link the disk - my $retry = 3; - my $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); - while ( $retry > 0 ) { - # wait 2 seconds for disk creation complete - sleep(2); - $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`; - $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + # Check if zhcp has the new routine to link and online the disk + $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/linkdiskandbringonline $userId $addr $mode"`; + $rc = $?; - if ($error) { - $retry -= 1; - $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); + $rc = $? >> 8; + if ($rc == 255) { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unable to communicate with zHCP agent: $hcp" ); + $error = 1; + } elsif ( $rc > 0 && $rc != 127 ) { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Unexpected error from SSH call to linkdiskandbringonline rc: $rc $out" ); + $error = 1; + } elsif ( $rc ==0 ) { + $newlinkcall = 1; + if ($out =~ m/Success:/i){ + # sample output=>linkdiskandbringonline maint start time: 2017-03-03-16:20:48.011 + # Success: Userid maint vdev 193 linked at ad35 device name dasdh + # linkdiskandbringonline exit time: 2017-03-03-16:20:52.150 + $out = `echo "$out" | egrep -a -i "Success:"`; + my @info = split( ' ', $out ); + $device = $info[10]; } else { - last; + xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to linkdiskandbringonline: $out" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM()(Error occurred in call to linkdiskandbringonline: $out" ); + $error = 1; } - } + } else { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Could not find zhcp linkdiskandbringonline, using old code path." ); + my $retry = 3; + $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); + while ( $retry > 0 ) { + # wait 2 seconds for disk creation complete + sleep(2); + $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp LINK TO $userId $addr AS $vdev M 2>&1"`; + $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; - # make the disk online and get it's device name - my $device = 0; - if ( !$error ) { - $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`; - $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev ); - my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices | grep -a 0.0.$vdev"`; - chomp( $select ); - # A sample entry: - # 0.0.1300(FBA ) at ( 94: 56) is dasdo : active at blocksize: 512, 7291441 blocks, 3560 MB - if ( $select ) { - my @info = split( ' ', $select ); - $device = "/dev/" . $info[7]; + if ($error) { + $retry -= 1; + $vdev = xCAT::zvmUtils->getFreeAddress( $::SUDOER, $hcp, 'vmcp' ); + } else { + last; + } + } + + # make the disk online and get it's device name + if ( !$error ) { + $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/cio_ignore -r $vdev &> /dev/null"`; + $out = xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-e", $vdev ); + my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat /proc/dasd/devices"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat /proc/dasd/devices\"", $hcp, "changeVM", $select, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + $error = 1; + } else { + $out = `echo "$out" | egrep -a -i "0.0.$vdev"`; + chomp( $select ); + # A sample entry: + # 0.0.0101(ECKD) at ( 94: 0) is dasda : active at blocksize: 4096, 600840 blocks, 2347 MB + if ( $select ) { + my @info = split( ' ', $select ); + $device = "/dev/" . $info[6]; + } + $error = !$device; + } } - $error = !$device; } #Delete the existing partition in case the disk already has partition on it @@ -1240,6 +1371,9 @@ d w EOF"`; $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during fdisk $device. Output: $out" ); + } } # Create one partition to use the entire disk space @@ -1254,15 +1388,24 @@ p w EOF"`; $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during fdisk to make a partition on $device. Output: $out" ); + } } if ( !$error ) { $device .= '1'; if ( $fstype =~ m/xfs/i ) { $out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs.xfs $device 2>&1"`; $error = (xCAT::zvmUtils->checkOutput( $out ) == -1) ? 1 : 0; + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during mkfs.xfs $device. Output: $out" ); + } } else { $out = `ssh $::SUDOER\@$hcp "$::SUDO mkfs -t $fstype $device 2>&1"`; $error = !($out =~ m/done/); + if ($error) { + xCAT::zvmUtils->printSyslog( "Error occurred during mkfs $fstype $device. Output: $out" ); + } } } if ( $error ) { @@ -1272,20 +1415,48 @@ EOF"`; $out = ""; } - xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev ); - `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`; - xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev"); - } + # offline and detach disk using new call so that zhcp records are updated + if ( $newlinkcall == 1 ){ + $out = `ssh -o ConnectTimeout=30 $::SUDOER\@$hcp "$::SUDO $::DIR/offlinediskanddetach $userId $addr"`; + $rc = $?; - # Add to active configuration - $out .= "Adding 9336 disk for $node as $addr ... Done"; - my $power = `/opt/xcat/bin/rpower $node stat`; - if ($power =~ m/: on/i) { - $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`; - xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode"); + $rc = $? >> 8; + if ( $rc == 255 ) { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Unable to communicate with zHCP agent" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM()( is unable to communicate with zHCP agent: $hcp" ); + $error = 1; + } + if ( $rc > 0 ) { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Unexpected error from SSH call to offlinediskanddetach rc: $rc $out" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM()Unexpected error from SSH call to offlinediskanddetach rc: $rc $out" ); + $error = 1; + } + if ($out =~ m/Success:/i){ + # sample output=>Success: Userid maint vdev 193 unlinked + xCAT::zvmUtils->printSyslog("$out"); + } else { + xCAT::zvmUtils->printSyslog( "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" ); + xCAT::zvmUtils->printLn( $callback, "$node: changeVM() Error occurred in call to offlinediskanddetach: $out" ); + $error = 1; + } + # Use old code to disable and detach + } else { + xCAT::zvmUtils->disableEnableDisk( $::SUDOER, $hcp, "-d", $vdev ); + `ssh $::SUDOER\@$hcp "$::SUDO /sbin/vmcp DETACH $vdev &> /dev/null"`; + xCAT::zvmUtils->printSyslog("vmcp DETACH $vdev"); + } } + if (!$error) { + # Add to active configuration + $out .= "Adding 9336 disk for $node as $addr ... Done"; + my $power = `/opt/xcat/bin/rpower $node stat`; + if ($power =~ m/: on/i) { + $out .= "\n" . `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Disk_Create -T $userId -v $addr -m $mode"`; + xCAT::zvmUtils->printSyslog("smcli Image_Disk_Create -T $userId -v $addr -m $mode"); + } - $out = xCAT::zvmUtils->appendHostname( $node, $out ); + $out = xCAT::zvmUtils->appendHostname( $node, $out ); + } } # adddisk2pool [function] [region] [volume] [group] @@ -1438,6 +1609,10 @@ EOF"`; if ($useWwpnLun) { # Store current attributes of the SCSI/FCP device in case need to roll back when something goes wrong my $deviceRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $wwpn, $lun); + if (xCAT::zvmUtils->checkOutput( $deviceRef ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$deviceRef" ); + return; + } %zFCP = %$deviceRef; # Check current status of the FCP device @@ -1582,9 +1757,13 @@ EOF"`; } # Check if the config file already exists and contains the zFCP channel - $cmd = $::SUDO . ' cat /etc/udev/rules.d/51-zfcp-0.0.' . $cur_device . '.rules | egrep -a -i ccw/0.0.' . $cur_device. ']online'; + $cmd = $::SUDO . ' cat /etc/udev/rules.d/51-zfcp-0.0.' . $cur_device . '.rules'; $out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd); if (xCAT::zvmUtils->checkOutput( $out ) == -1) { + return; + } + $out = `echo "$out" | egrep -a -i 'ccw/0.0.' . $cur_device. ']online'`; + if (!(length $out)) { # Configure zFCP device to be persistent $cmd = "$::SUDO touch /etc/udev/rules.d/51-zfcp-0.0.$cur_device.rules"; $out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd, $callback); @@ -2022,8 +2201,12 @@ EOF"`; next; } - $cmd = $::SUDO . ' /sbin/udevadm info --query=all --name=' . $srcFile . ' | grep -a "ID_SERIAL="'; - $out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd); + $cmd = $::SUDO . ' /sbin/udevadm info --query=all --name=' . $srcFile; + $out = xCAT::zvmUtils->execcmdonVM($::SUDOER, $node, $cmd, $callback); + if (xCAT::zvmUtils->checkOutput( $out ) == -1) { + return; + } + $out = `echo "$out" | egrep -a -i "ID_SERIAL="`; $out =~ m/ID_SERIAL=(\w+)\s*$/; $wwid = $1; if ($wwid) { last; } @@ -2522,13 +2705,23 @@ EOF"`; # Find the pool that contains the SCSI/FCP device my $pool = xCAT::zvmUtils->findzFcpDevicePool($::SUDOER, $hcp, $wwpn, $lun); + if (xCAT::zvmUtils->checkOutput( $pool ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$pool" ); + return; + } if (!$pool) { # Continue to try and remove the SCSI/FCP device even when it is not found in a storage pool xCAT::zvmUtils->printLn( $callback, "$node: Could not find FCP device in any FCP storage pool" ); } else { xCAT::zvmUtils->printLn( $callback, "$node: Found FCP device in $pool" ); - my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf" | grep -a -i "$wwpn,$lun"`; + my $select = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$pool.conf\" ", $hcp, "changeVM", $select, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $select = `echo "$select" | egrep -a -i "$wwpn,$lun"`; chomp($select); my @info = split(',', $select); @@ -2873,8 +3066,14 @@ EOF"`; '30','31','32','33','34','35','36','37','39','39','3A','3B','3C','3D','3E','3F'); # Get current CPU count and address - my $proc = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $userId -k CPU" | grep -a CPU=`; - xCAT::zvmUtils->printSyslog("smcli Image_Definition_Query_DM -T $userId -k CPU | grep -a CPU="); + xCAT::zvmUtils->printSyslog("smcli Image_Definition_Query_DM -T $userId -k CPU"); + my $proc = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $userId -k CPU"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli Image_Definition_Query_DM -T $userId -k CPU\"", $hcp, "changeVM", $proc, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $proc = `echo "$proc" | egrep -a -i CPU=`; while ( index( $proc, "CPUADDR" ) != -1) { my $position = index($proc, "CPUADDR"); my $address = substr($proc, $position + 8, 2); @@ -3420,8 +3619,6 @@ sub powerVM { xCAT::zvmUtils->printLn( $callback, "$node: unreachable"); return; } - - # Create output string if ($out) { xCAT::zvmUtils->printLn( $callback, "$node: reachable"); @@ -3648,7 +3845,7 @@ sub scanVM { Description : Get hardware and software inventory of a given node Arguments : Node Type of inventory (all|config|console [logsize]|cpumem|cpumempowerstat|--freerepospace) - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : inventoryVM($callback, $node, $args); =cut @@ -3662,6 +3859,9 @@ sub inventoryVM { # Output string my $str = ""; + my $outmsg; + my $rc; + # Check if node is pingable if (($args->[0] ne '--consoleoutput') and ($args->[0] ne 'cpumempowerstat')){ my $ping = xCAT::zvmUtils->pingNode($node); @@ -3752,6 +3952,10 @@ sub inventoryVM { # Get instance CPU used time my $cputime = xCAT::zvmUtils->getUsedCpuTime($::SUDOER, $hcp , $node); + if (xCAT::zvmUtils->checkOutput( $cputime ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$cputime" ); + return; + } $str .= "Total Memory: $memory\n"; $str .= "Processors: \n$proc\n"; @@ -3856,6 +4060,10 @@ sub inventoryVM { # Get instance CPU used time my $cputime = xCAT::zvmUtils->getUsedCpuTime($::SUDOER, $hcp , $node); + if (xCAT::zvmUtils->checkOutput( $cputime ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$cputime" ); + return; + } # Create output string $str .= "z/VM UserID: $userId\n"; @@ -3914,7 +4122,13 @@ sub inventoryVM { xCAT::zvmUtils->printSyslog( "vmcp spool c class return: $out" ); # Get console output from zhcp - $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/sbin/vmur list | egrep -a -i $userId "`; + $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/sbin/vmur list"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO /usr/sbin/vmur list\"", $hcp, "inventoryVM", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "$userId "`; my @spoolFiles = sort(split('\n', $out)); $str = ""; foreach (@spoolFiles){ @@ -4206,6 +4420,8 @@ sub makeVM { # Create a new user in zVM without user directory entry file my $out; + my $outmsg; + my $rc; my $stdin; my $password = ""; my $memorySize = ""; @@ -4313,14 +4529,20 @@ sub makeVM { $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "/sbin/modprobe vmcp"`; # Get USER Prefix - my $prefix = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q vmlan" | egrep -a -i "USER Prefix:"`; + my $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q vmlan"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $::SUDOER\@$hcp \"$::SUDO /sbin/vmcp q vmlan\"", $hcp, "makeVM", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + my $prefix = `echo "$out" | egrep -a -i "USER Prefix:"`; $prefix =~ s/(.*?)USER Prefix:(.*)/$2/; $prefix =~ s/^\s+//; $prefix =~ s/\s+$//; # Get MACADDR Prefix instead if USER Prefix is not defined if (!$prefix) { - $prefix = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q vmlan" | egrep -a -i "MACADDR Prefix:"`; + $prefix = `echo "$out" | egrep -a -i "MACADDR Prefix:"`; $prefix =~ s/(.*?)MACADDR Prefix:(.*)/$2/; $prefix =~ s/^\s+//; $prefix =~ s/\s+$//; @@ -4387,7 +4609,6 @@ sub makeVM { my $oldNicDef; my $nicDef; my $id; - my $rc; my @vswId; my $target = "$::SUDOER\@$hcp"; if ($userEntry) { @@ -4619,6 +4840,10 @@ sub cloneVM { my $sourceIp = xCAT::zvmUtils->getIp($sourceNode); my @dedicates = xCAT::zvmUtils->getDedicates( $callback, $::SUDOER, $sourceNode ); + if (xCAT::zvmUtils->checkOutput( $dedicates[0] ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$dedicates[0]" ); + return; + } if (scalar(@dedicates)) { xCAT::zvmUtils->printLn( $callback, "$sourceNode: (Error) Dedicate statements found in source directory." ); return; @@ -4728,6 +4953,10 @@ sub cloneVM { # Create MAC address (target) $targetMac = xCAT::zvmUtils->createMacAddr( $::SUDOER, $_, $macId ); + if (xCAT::zvmUtils->checkOutput( $targetMac ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$targetMac" ); + return; + } # Save MAC address in 'mac' table xCAT::zvmUtils->setNodeProp( 'mac', $_, 'mac', $targetMac ); @@ -4756,6 +4985,10 @@ sub cloneVM { # $srcLinkAddr[$addr] = $type my %srcDiskType; my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $::SUDOER, $sourceNode ); + if (xCAT::zvmUtils->checkOutput( $srcDisks[0] ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$srcDisks[0]" ); + return; + } # Get details about source disks # Output is similar to: @@ -4938,6 +5171,10 @@ sub cloneVM { my $srcUserEntry = "/tmp/$sourceNode.txt"; $out = `rm $srcUserEntry`; $out = xCAT::zvmUtils->getUserEntryWODisk( $callback, $::SUDOER, $sourceNode, $srcUserEntry ); + if (xCAT::zvmUtils->checkOutput( $out ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$out" ); + return; + } # Check if user entry is valid $out = `cat $srcUserEntry`; @@ -5074,7 +5311,7 @@ sub cloneVM { Root parition device address Path to network configuration file Path to hardware configuration file (SUSE only) - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : clone($callback, $_, $args, \@srcDisks, \%srcLinkAddr, \%srcDiskSize, $srcNicAddr, $hcpNetName, \@srcVswitch, $srcOs, $srcMac, $netEntries, $sourceIp, $srcNetwork, $srcMask); @@ -5162,6 +5399,7 @@ sub clone { xCAT::zvmUtils->printSyslog("hcp:$hcp tgtUserId:$tgtUserId targetIp:$targetIp"); my $out; + my $outmsg; my @lines; my @words; @@ -5454,8 +5692,14 @@ sub clone { while ( $try > 0 ) { # Get disks within user entry - $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId" | sed '\$d' | grep -a "MDISK"`; - xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId | grep -a MDISK"); + xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId"); + $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId\"", $hcp, "clone", $out, $tgtNode ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | sed '\$d' | grep -a -i "MDISK"`; xCAT::zvmUtils->printSyslog("$out"); @disks = split( '\n', $out ); @@ -5795,12 +6039,24 @@ sub clone { while (!$out && $try > 0) { # Check if /usr/bin/file is available if (`ssh $::SUDOER\@$hcp "$::SUDO test -f /usr/bin/file && echo Exists"`) { - $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/bin/file -s /dev/$tgtDevNode*" | grep -a -v swap | grep -a -o "$tgtDevNode\[1-9\]"`; + xCAT::zvmUtils->printSyslog("ssh $::SUDOER\@$hcp \"$::SUDO /usr/bin/file -s /dev/$tgtDevNode*\""); + $out = `ssh $::SUDOER\@$hcp "$::SUDO /usr/bin/file -s /dev/$tgtDevNode*"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO /usr/bin/file -s /dev/$tgtDevNode*\"", $hcp, "clone", $out, $tgtDevNode ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } } else { - $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/fdisk -l /dev/$tgtDevNode* | grep -a -v swap | grep -a -o $tgtDevNode\[1-9\]"`; + xCAT::zvmUtils->printSyslog("ssh $::SUDOER\@$hcp \"$::SUDO /sbin/fdisk -l /dev/$tgtDevNode*\""); + $out = `ssh $::SUDOER\@$hcp "$::SUDO /sbin/fdisk -l /dev/$tgtDevNode*"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO /sbin/fdisk -l /dev/$tgtDevNode*\"", $hcp, "clone", $out, $tgtDevNode ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } } + $out = `echo "$out" | egrep -a -i -v swap | egrep -a -o "$tgtDevNode\[1-9\]"`; $out = xCAT::zvmUtils->trimStr($out); - xCAT::zvmUtils->printSyslog("fdisk -l /dev/$tgtDevNode* | grep -a -v swap | grep -a -o $tgtDevNode\[1-9\]"); xCAT::zvmUtils->printSyslog("$out"); # Wait before trying again @@ -5868,8 +6124,14 @@ sub clone { # If it is Red Hat - ifcfg-qeth file is in /etc/sysconfig/network-scripts my @files; if ( $srcOs =~ m/rhel/i ) { - $out = `ssh $::SUDOER\@$hcp "$::SUDO grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts | grep -a -i 'ifcfg-eth' "`; xCAT::zvmUtils->printSyslog("grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts"); + $out = `ssh $::SUDOER\@$hcp "$::SUDO grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO grep -a -H -i -r $srcNicAddr $cloneMntPt/etc/sysconfig/network-scripts\"", $hcp, "clone", $out, $tgtDevNode ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i 'ifcfg-eth'`; xCAT::zvmUtils->printSyslog("$out"); @files = split('\n', $out); @words = split( ':', $files[0] ); @@ -5932,15 +6194,20 @@ sub clone { # Set MAC address my $networkFile = $tgtNode . "NetworkConfig"; my $config; - if ( $srcOs =~ m/rhel/i ) { + $config = `ssh $::SUDOER\@$hcp "$::SUDO cat $ifcfgPath"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $ifcfgPath\"", $hcp, "clone", $config, $tgtDevNode ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + if ( $srcOs =~ m/rhel/i ) { # Red Hat only - $config = `ssh $::SUDOER\@$hcp "$::SUDO cat $ifcfgPath" | grep -a -v "MACADDR"`; + $config = `echo "$config" | egrep -a -i -v "MACADDR"`; $config .= "MACADDR='" . $targetMac . "'\n"; } else { - # SUSE only - $config = `ssh $::SUDOER\@$hcp "$::SUDO cat $ifcfgPath" | grep -a -v "LLADDR" | grep -a -v "UNIQUE"`; + $config = `echo "$config" | egrep -a -i -v "LLADDR" | egrep -a -i -v "UNIQUE"`; # Set to MAC address (only for layer 2) if ( $layer == 2 ) { @@ -6033,7 +6300,7 @@ sub clone { * Punch initrd, kernel, and parmfile to node reader * Layer 2 and 3 VSwitch/Lan supported Arguments : Node - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : nodeSet($callback, $node, $args); =cut @@ -6158,6 +6425,7 @@ sub nodeSet { # Get action my $out; + my $outmsg; if ( $action eq "install" ) { # Get node root password @@ -6611,7 +6879,13 @@ sub nodeSet { my $zfcpSection = ""; foreach (@pools) { if (!(length $_)) {next;} - $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_" | egrep -a -i ",$node,"`; + $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$_\"", $hcp, "nodeSet", $entry, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $entry = `echo "$entry" | egrep -a -i ",$node,"`; chomp($entry); if (!$entry) { next; @@ -6895,7 +7169,13 @@ END my $zfcpSection = ""; foreach (@pools) { if (!(length $_)) {next;} - $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_" | egrep -a -i ",$node,"`; + $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$_"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$_\"", $hcp, "nodeSet", $entry, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $entry = `echo "$entry" | egrep -a -i ",$node,"`; chomp($entry); if (!$entry) { next; @@ -6973,6 +7253,10 @@ END # Get mdisk virtual address my @mdisks = xCAT::zvmUtils->getMdisks( $callback, $::SUDOER, $node ); + if (xCAT::zvmUtils->checkOutput( $mdisks[0] ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$mdisks[0]" ); + return; + } @mdisks = sort(@mdisks); my $dasd = ""; my $devices = ""; @@ -6998,6 +7282,10 @@ END # Get dedicated virtual address my @dedicates = xCAT::zvmUtils->getDedicates( $callback, $::SUDOER, $node ); + if (xCAT::zvmUtils->checkOutput( $dedicates[0] ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$dedicates[0]" ); + return; + } @dedicates = sort(@dedicates); $i = 0; foreach (@dedicates) { @@ -7217,7 +7505,13 @@ END my $tmpInitFile = "/tmp/$os-initrd-statelite.gz"; xCAT::zvmUtils->printLn( $callback, "$node: Looking for kernel $os-kernel." ); - if (`ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp" | grep -a "$os-kernel"`) { + $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $::SUDOER\@$hcp \"$::SUDO ls /tmp\"", $hcp, "nodeSet", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + if (`echo "$out" | egrep -a -i "$os-kernel"`) { # Do nothing } else { # Send kernel to reader to HCP @@ -7225,14 +7519,14 @@ END xCAT::zvmUtils->printLn( $callback, "sendfile $kernelFile, $tmpKernelFile" ); } - if (`ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp" | grep -a "$os-parm-statelite"`) { + if (`echo "$out" | egrep -a -i "$"os-parm-statelite"`) { # Do nothing } else { # Send parmfile to reader to HCP xCAT::zvmUtils->sendFile( $::SUDOER, $hcp, $parmFile, $tmpParmFile ); } - if (`ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO ls /tmp" | grep -a "$os-initrd-statelite.gz"`) { + if (`echo "$out" | egrep -a -i "$os-initrd-statelite.gz"`) { # Do nothing } else { # Send initrd to reader to HCP @@ -7314,6 +7608,10 @@ END # Handle sysclone which can have multiple image files which MUST match each mdisk # Get the list of mdisks my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $::SUDOER, $node ); + if (xCAT::zvmUtils->checkOutput( $srcDisks[0] ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$srcDisks[0]" ); + return; + } # Verify the list of images and matching disks my $validArrayDisks = 0; @@ -7561,7 +7859,7 @@ END * Requires the node be online * Saves MAC address in 'mac' table Arguments : Node - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : getMacs($callback, $node, $args); =cut @@ -7579,6 +7877,10 @@ sub getMacs { GetOptions( 'f' => \$force ); } + my $out; + my $outmsg; + my $rc; + # Get node properties from 'zvm' table my @propNames = ( 'hcp', 'userid' ); my $propVals = xCAT::zvmUtils->getNodeProps( 'zvm', $node, @propNames ); @@ -7615,7 +7917,13 @@ sub getMacs { xCAT::zvmCPUtils->loadVmcp($::SUDOER, $node); # Get xCat MN Lan/VSwitch name - my $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q v nic" | egrep -a -i "VSWITCH|LAN"`; + $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/vmcp q v nic"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh -o ConnectTimeout=5 $::SUDOER\@$hcp \"$::SUDO /sbin/vmcp q v nic\"", $hcp, "getMacs", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "VSWITCH|LAN"`; my @lines = split( '\n', $out ); my @words; @@ -8054,6 +8362,10 @@ sub listTree { # Find out if this z/VM belongs to an SSI cluster $ssi{$node} = xCAT::zvmUtils->querySSI($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $ssi{$node} ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$ssi{$node}" ); + return; + } # Find CEC root based on LPAR # CEC -> LPAR @@ -8182,7 +8494,7 @@ sub listTree { Description : Configure the virtualization hosts Arguments : Node Arguments - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : changeHypervisor($callback, $node, $args); =cut @@ -8219,6 +8531,8 @@ sub changeHypervisor { # Output string my $out = ""; + my $outmsg; + my $rc; # adddisk2pool [function] [region] [volume] [group] if ( $args->[0] eq "--adddisk2pool" ) { @@ -8552,11 +8866,19 @@ sub changeHypervisor { xCAT::zvmUtils->printLn( $callback, "$node: (Error) Failed to find FCP device in any zFCP storage pool" ); return; } else { + if (xCAT::zvmUtils->checkOutput( $pool ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$pool" ); + return; + } xCAT::zvmUtils->printLn( $callback, "$node: Found FCP device in $pool" ); } # Get source device's attributes my $srcDiskRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $srcWwpn, $srcLun); + if (xCAT::zvmUtils->checkOutput( $srcDiskRef ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$srcDiskRef" ); + return; + } my %srcDisk = %$srcDiskRef; if (!defined($srcDisk{'lun'}) && !$srcDisk{'lun'}) { xCAT::zvmUtils->printLn( $callback, "$node: (Error) Source zFCP device $srcWwpn/$srcLun does not exists" ); @@ -8568,6 +8890,10 @@ sub changeHypervisor { my $tgtSize; if ($useWwpnLun) { my $tgtDiskRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $tgtWwpn, $tgtLun); + if (xCAT::zvmUtils->checkOutput( $tgtDiskRef ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$tgtDiskRef" ); + return; + } my %tgtDisk = %$tgtDiskRef; if (!defined($tgtDisk{'lun'}) && !$tgtDisk{'lun'}) { xCAT::zvmUtils->printLn( $callback, "$node: (Error) Target zFCP device $tgtWwpn/$tgtLun does not exists" ); @@ -8793,11 +9119,19 @@ sub changeHypervisor { xCAT::zvmUtils->printLn($callback, "$node: (Error) Failed to find FCP device in any zFCP storage pool"); return; } else { + if (xCAT::zvmUtils->checkOutput( $pool ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$pool" ); + return; + } xCAT::zvmUtils->printLn($callback, "$node: Found FCP device in $pool"); } # Get source device's attributes my $srcDiskRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $wwpn, $lun); + if (xCAT::zvmUtils->checkOutput( $srcDiskRef ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$srcDiskRef" ); + return; + } my %srcDisk = %$srcDiskRef; if (!defined($srcDisk{'lun'}) && !$srcDisk{'lun'}) { xCAT::zvmUtils->printLn($callback, "$node: (Error) Source zFCP device $wwpn/$lun does not exists"); @@ -8972,6 +9306,10 @@ sub changeHypervisor { xCAT::zvmUtils->printLn($callback, "$node: (Error) Failed to find FCP device in any zFCP storage pool"); return; } else { + if (xCAT::zvmUtils->checkOutput( $pool ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$pool" ); + return; + } xCAT::zvmUtils->printLn($callback, "$node: Found FCP device in $pool"); } @@ -9154,7 +9492,13 @@ sub changeHypervisor { my $cur_lun = $_; if (!(length $cur_lun)) {next;} # Entry should contain: status, wwpn, lun, size, range, owner, channel, tag - $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf" | egrep -a -i $cur_lun`; + $entry = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$pool.conf\"", $hcp, "changeHypervisor", $entry, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $entry = `echo "$entry" | egrep -a -i "$cur_lun"`; # Do not update if LUN does not exists, stop checking other luns if this one not found if (!$entry) { xCAT::zvmUtils->printLn( $callback, "$node: (Error) zFCP device $cur_lun does not exist" ); @@ -9285,6 +9629,10 @@ sub changeHypervisor { if ($wwpn && $lun) { # Check the status of the FCP device my $deviceRef = xCAT::zvmUtils->findzFcpDeviceAttr($::SUDOER, $hcp, $pool, $wwpn, $lun); + if (xCAT::zvmUtils->checkOutput( $deviceRef ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$deviceRef" ); + return; + } my %zFCP = %$deviceRef; if ($zFCP{'status'} eq 'used') { xCAT::zvmUtils->printLn($callback, "$node: (Error) FCP device 0x$wwpn/0x$lun is in use."); @@ -9386,7 +9734,7 @@ sub changeHypervisor { Description : Get hardware and software inventory of a given hypervisor Arguments : Node Type of inventory (config|all) - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : inventoryHypervisor($callback, $node, $args); =cut @@ -9404,6 +9752,8 @@ sub inventoryHypervisor { my $str = ""; my $rc; + my $out; + my $outmsg; # Get node properties from 'zvm' table my @propNames = ( 'hcp' ); @@ -9422,7 +9772,7 @@ sub inventoryHypervisor { my $hcpUserId = xCAT::zvmCPUtils->getUserId($::SUDOER, $hcp); # Load VMCP module - my $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/modprobe vmcp"`; + $out = `ssh -o ConnectTimeout=5 $::SUDOER\@$hcp "$::SUDO /sbin/modprobe vmcp"`; # Get configuration if ( $args->[0] eq 'config' ) { @@ -9431,18 +9781,38 @@ sub inventoryHypervisor { # Get total physical CPU in this LPAR my $lparCpuTotal = xCAT::zvmUtils->getLparCpuTotal($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparCpuTotal ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparCpuTotal" ); + return; + } # Get used physical CPU in this LPAR my $lparCpuUsed = xCAT::zvmUtils->getLparCpuUsed($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparCpuUsed ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparCpuUsed" ); + return; + } # Get LPAR memory total my $lparMemTotal = xCAT::zvmUtils->getLparMemoryTotal($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparMemTotal ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparMemTotal" ); + return; + } # Get LPAR memory Offline my $lparMemOffline = xCAT::zvmUtils->getLparMemoryOffline($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparMemOffline ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparMemOffline" ); + return; + } # Get LPAR memory Used my $lparMemUsed = xCAT::zvmUtils->getLparMemoryUsed($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparMemUsed ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparMemUsed" ); + return; + } $str .= "z/VM Host: $hypname\n"; $str .= "zHCP: $hcp\n"; @@ -9458,18 +9828,38 @@ sub inventoryHypervisor { my $hypname = xCAT::zvmCPUtils->getHost($::SUDOER, $hcp); # Get total physical CPU in this LPAR my $lparCpuTotal = xCAT::zvmUtils->getLparCpuTotal($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparCpuTotal ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparCpuTotal" ); + return; + } # Get used physical CPU in this LPAR my $lparCpuUsed = xCAT::zvmUtils->getLparCpuUsed($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparCpuUsed ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparCpuUsed" ); + return; + } # Get CEC model my $cecModel = xCAT::zvmUtils->getCecModel($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $cecModel ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$cecModel" ); + return; + } # Get vendor of CEC my $cecVendor = xCAT::zvmUtils->getCecVendor($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $cecVendor ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$cecVendor" ); + return; + } # Get hypervisor type and version my $hvInfo = xCAT::zvmUtils->getHypervisorInfo($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $hvInfo ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$hvInfo" ); + return; + } # Get processor architecture my $arch = xCAT::zvmUtils->getArch($::SUDOER, $hcp); @@ -9479,12 +9869,24 @@ sub inventoryHypervisor { # Get LPAR memory total my $lparMemTotal = xCAT::zvmUtils->getLparMemoryTotal($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparMemTotal ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparMemTotal" ); + return; + } # Get LPAR memory Offline my $lparMemOffline = xCAT::zvmUtils->getLparMemoryOffline($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparMemOffline ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparMemOffline" ); + return; + } # Get LPAR memory Used my $lparMemUsed = xCAT::zvmUtils->getLparMemoryUsed($::SUDOER, $hcp); + if (xCAT::zvmUtils->checkOutput( $lparMemUsed ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$lparMemUsed" ); + return; + } # Get IPL Time my $ipl = xCAT::zvmCPUtils->getIplTime($::SUDOER, $hcp); @@ -9653,8 +10055,14 @@ sub inventoryHypervisor { } } } else { - $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_WWPN_Query -T $hcpUserId" | egrep -a -i "FCP device number|Status"`; - xCAT::zvmUtils->printSyslog("smcli System_WWPN_Query -T $hcpUserId | egrep -a -i FCP device number|Status"); + xCAT::zvmUtils->printSyslog("smcli System_WWPN_Query -T $hcpUserId"); + $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_WWPN_Query -T $hcpUserId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli System_WWPN_Query -T $hcpUserId\"", $hcp, "inventoryHypervisor", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "FCP device number|Status"`; @devices = split( "\n", $out ); for ($i = 0; $i < @devices; $i++) { @@ -9691,8 +10099,14 @@ sub inventoryHypervisor { return; } - $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp" | egrep -a -i "FCP device number:|World wide port number:|Logical unit number:|Number of bytes residing on the logical unit:"`; - xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp | egrep -a -i FCP device number:|World wide port number:|Logical unit number:|Number of bytes residing on the logical unit:"); + xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp"); + $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp\"", $hcp, "inventoryHypervisor", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "FCP device number:|World wide port number:|Logical unit number:|Number of bytes residing on the logical unit:"`; my @wwpns = split( "\n", $out ); my %map; @@ -9908,8 +10322,14 @@ sub inventoryHypervisor { return; } - $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp" | egrep -a -i "World wide port number:"`; - xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp | egrep -a -i World wide port number:"); + xCAT::zvmUtils->printSyslog("smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp"); + $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli System_FCP_Free_Query -T $hcpUserId -k fcp_dev=$fcp\"", $hcp, "inventorHypervisor", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "World wide port number:"`; my @wwpns = split( "\n", $out ); my %uniqueWwpns; @@ -9942,7 +10362,14 @@ sub inventoryHypervisor { $str = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`; } else { $str = "#status,wwpn,lun,size,range,owner,channel,tag\n"; - $str .= `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf" | egrep -a -i $space`; + $out = `ssh $::SUDOER\@$hcp "$::SUDO cat $::ZFCPPOOL/$pool.conf"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO cat $::ZFCPPOOL/$pool.conf\"", $hcp, "inventoryHypervisor", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "$space"`; + $str .= $out; } } @@ -10421,7 +10848,7 @@ sub eventLog { Profile Device information Compression level: 0 - none, 1 thru 9 - gzip compression level - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : imageCapture( $callback, $node, $os, $arch, $type, $profile, $osimg, $device, $comp ); =cut @@ -10431,6 +10858,7 @@ sub imageCapture { my ($class, $callback, $node, $os, $arch, $type, $profile, $osimg, $device, $comp) = @_; my $rc; my $out = ''; + my $outmsg; my $reason = ""; my $provMethod; my $compParm = ""; @@ -10532,12 +10960,12 @@ sub imageCapture { if ($devName eq '/dev/root') { # Determine which Linux device is associated with the root directory #$out = `ssh $sudoer\@$node $sudo 'cat /proc/cmdline | tr " " "\\n" | grep -a "^root=" | cut -c6-'`; - $cmd = "$::SUDO" . ' cat /proc/cmdline | tr " " "\\n" | grep -a "^root=" | cut -c6-'; + $cmd = "$::SUDO" . ' cat /proc/cmdline | tr " " "\\n"'; $out = xCAT::zvmUtils->execcmdonVM($sudoer, $node, $cmd, $callback); if (xCAT::zvmUtils->checkOutput( $out ) == -1) { return; } - + $out = `echo "$out" | egrep -a -i "^root=" | cut '-c6-'`; my $rootDev = ''; if ($out) { @@ -10596,6 +11024,10 @@ sub imageCapture { # Get the list of mdisks my @srcDisks = xCAT::zvmUtils->getMdisks( $callback, $sudoer, $node ); + if (xCAT::zvmUtils->checkOutput( $srcDisks[0] ) == -1) { + xCAT::zvmUtils->printLn( $callback, "$srcDisks[0]" ); + return; + } foreach (@srcDisks) { # Get disk address my @words = split( ' ', $_ ); @@ -10691,11 +11123,23 @@ sub imageCapture { # Wait (checking every 15 seconds) until user is finally logged off or maximum wait time has elapsed my $max = 0; - $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null | grep -a HCPCQU045E"`; + $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $sudoer\@$hcp \"$sudo /sbin/vmcp q user $targetUserId 2>/dev/null\"", $hcp, "imageCapture", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "HCPCQU045E"`; while ( !$out && $max < 60 ) { sleep(15); # Wait 15 seconds $max++; - $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null | grep -a HCPCQU045E"`; + $out=`ssh $sudoer\@$hcp "$sudo /sbin/vmcp q user $targetUserId 2>/dev/null"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $sudoer\@$hcp \"$sudo /sbin/vmcp q user $targetUserId 2>/dev/null\"", $hcp, "imageCapture", $out, $node ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | egrep -a -i "HCPCQU045E"`; } my $totalMinutes = $max * 15 / 60; if ( $out ) { @@ -11286,7 +11730,7 @@ sub specialcloneVM { clone info hash from doclone.txt Source zvm userid Source userid directory file name - Returns : Nothing + Returns : Nothing, errors returned in $callback Example : specialClone($callback, $_, $args, \@srcMdisks, \%srcLinkAddr, \%cloneInfoHash, $sourceId, $srcUserEntry); =cut @@ -11348,6 +11792,7 @@ sub specialClone { $hcpUserId =~ tr/a-z/A-Z/; my $out; + my $outmsg; my @lines; my @words; @@ -11551,8 +11996,14 @@ sub specialClone { while ( $try > 0 ) { # Get disks within user entry - $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId" | sed '\$d' | grep -a "MDISK"`; - xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId | grep -a MDISK"); + xCAT::zvmUtils->printSyslog("smcli Image_Query_DM -T $tgtUserId"); + $out = `ssh $::SUDOER\@$hcp "$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId"`; + ($rc, $outmsg) = xCAT::zvmUtils->checkSSH_Rc( $?, "ssh $::SUDOER\@$hcp \"$::SUDO $::DIR/smcli Image_Query_DM -T $tgtUserId\"", $hcp, "specialClone", $out, $tgtNode ); + if ($rc != 0) { + xCAT::zvmUtils->printLn( $callback, "$outmsg" ); + return; + } + $out = `echo "$out" | sed '\$d' | grep -a -i "MDISK"`; xCAT::zvmUtils->printSyslog("$out"); @disks = split( '\n', $out ); diff --git a/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm b/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm index b6bc8debe..66d5e6808 100644 --- a/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm +++ b/xCAT-server/lib/xcat/plugins/zvmdiscovery.pm @@ -1945,8 +1945,9 @@ sub startDiscovery{ 'ldapsrv', 'lohcost', 'maint', 'maint630', 'maint640', 'migmaint', 'monwrite', 'mproute', - 'operator', 'operatns', 'opersymp', 'opncloud', 'osadmin1', 'osadmin2', - 'osadmin3', 'osamaint', 'osasf', 'ovfdev62', + 'operator', 'operatns', 'opersymp', 'opncloud', + 'osadmin1', 'osadmin2', 'osadmin3', + 'osamaint', 'osasf', 'ovfdev62', 'perfsvm', 'persmapi', 'pmaint', 'portmap', 'racfsmf', 'racfvm', 'racmaint', 'rexecd', 'rscs', 'rscsauth', 'rscsdns', 'rxagent1', @@ -1955,8 +1956,8 @@ sub startDiscovery{ 'tcpip', 'tcpmaint', 'tsafvm', 'uftd', 'vmnfs', 'vmrmadmn', 'vmrmsvm', - 'vmservp', 'vmservr', 'vmservu', 'vmservs', 'vsmevsrv', - 'vsmguard', 'vsmproxy', 'vsmreqim', 'vsmreqin', 'vsmreqiu', + 'vmservp', 'vmservr', 'vmservu', 'vmservs', 'vsmevsrv', + 'vsmguard', 'vsmproxy', 'vsmreqim', 'vsmreqin', 'vsmreqiu', 'vsmreqi6', 'vsmwork1', 'vsmwork2', 'vsmwork3', 'vsmwork4', 'vsmwork5', 'vsmwork6', 'vsmwork7', 'vsmwork8', 'vsmwork9', 'xcat', 'xcatserv', 'xchange', diff --git a/xCAT-server/xCAT-server.spec b/xCAT-server/xCAT-server.spec index 2013dcf11..53f239709 100644 --- a/xCAT-server/xCAT-server.spec +++ b/xCAT-server/xCAT-server.spec @@ -46,9 +46,8 @@ Obsoletes: atftp-xcat %ifos linux # # PCM does not use or ship grub2-xcat -Requires: grub2-xcat perl-Net-HTTPS-NB perl-HTTP-Async %if %nots390x -Requires: grub2-xcat +Requires: grub2-xcat perl-Net-HTTPS-NB perl-HTTP-Async %endif %endif %endif diff --git a/xCAT-server/xCAT-wsapi/xcatws.cgi b/xCAT-server/xCAT-wsapi/xcatws.cgi index a5e8c39dd..84701929a 100755 --- a/xCAT-server/xCAT-wsapi/xcatws.cgi +++ b/xCAT-server/xCAT-wsapi/xcatws.cgi @@ -1,1310 +1,35 @@ #!/usr/bin/perl -# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html use strict; -use CGI qw/:standard/; #todo: remove :standard when the code only uses object oriented interface +use CGI qw/:standard/; +#use JSON; # require this dynamically later on so that installations that do not use xcatws.cgi do not need perl-JSON use Data::Dumper; -#talk to the server -use Socket; -use IO::Socket::INET; -use IO::Socket::SSL; - -# The hash %URIdef defines all the xCAT resources which can be access from Web Service. -# This script will be called when a https request with the URI started with /xcatws/ is sent to xCAT Web Service -# Inside this script: -# 1. The main body parses the URI and parameters -# 2. Base on the URI, go through the %URIdef to find the matched resource by the 'matcher' which is defined for each resource -# 3. Call the 'fhandler' which is defined in the resource to communicate with xcatd and get the xml response -# 3.1 The 'fhandler' generates the xml request base on the resource, parameters and http method 'GET|PUT|POST|DELETE', sends to xcatd and then get the xml response -# 4. Call the 'outhdler' which is defined in the resource to parse the xml response and translate it to JSON format -# 5. Output the http response to STDOUT +#added the line: +#ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi +#to /etc/httpd/conf/httpd.conf to hid the cgi-bin and .cgi extension in the uri # -# Refer to the $URIdef{node}->{allnode} and $URIdef{node}->{nodeallattr} for your new created resource definition. -# -# |--node - Resource Group -# | `--allnode - Resource Name -# | `--desc - Description for the Resource -# | `--desc[1..10] - Additional description for the Resource -# | `--matcher - The matcher which is used to match the URI to the Resource -# | `--GET - The info is used to handle the GET request -# | `--desc - Description for the GET operation -# | `--desc[1..10] - Additional description for the GET operation -# | `--usage - Usage message. The format must be '|Parameters for the GET request|Returns for the GET request|'. The message in the '|' can be black, but the delimiter '|' must be kept. -# | `--example - Example message. The format must be '|Description|GET|URI PUT/POST_data|Return Msg|'. The messages in the four sections must be completed. -# | `--cmd - The xCAT command line coammnd which will be used to complete the request. It's not a must have attribute. -# | `--fhandler - The call back subroutine which is used to handle the GET request. Generally, it parses the parameters from request and then call xCAT command. This subroutine can be exclusive or shared. -# | `--outhdler - The call back subroutine which is used to handle the GET request. Generally, it parses the xml output from the 'fhandler' and then format the output to JSON. This subroutine can be exclusive or shared. -# | `--PUT - The info is used to handle the PUT request -# | `--POST - The info is used to handle the POST request -# | `--DELETE - The info is used to handle the DELETE request +# also upgraded CGI to 3.52 -# The common messages which can be used in the %URIdef -my %usagemsg = ( - objreturn => "Json format: An object which includes multiple \' : {att:value, attr:value ...}\' pairs.", - objchparam => "Json format: An object which includes multiple \'att:value\' pairs.", - non_getreturn => "No output when execution is successfull. Otherwise output the error information in the Standard Error Format: {error:[msg1,msg2...],errocode:errornum}." -); +#take the JSON or XML and put it into a data structure +#all data input will be done from the common structure -my %URIdef = ( - #### definition for node resources - nodes => { - allnode => { - desc => "[URI:/nodes] - The node list resource.", - desc1 => "This resource can be used to display all the nodes which have been defined in the xCAT database.", - matcher => '^/nodes$', - GET => { - desc => "Get all the nodes in xCAT.", - desc1 => "The attributes details for the node will not be displayed.", - usage => "||Json format: An array of node names.|", - example => "|Get all the node names from xCAT database.|GET|/nodes|[\n \"node1\",\n \"node2\",\n \"node3\",\n]|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout_remove_appended_type, - } - }, - nodeallattr => { - desc => "[URI:/nodes/{noderange}] - The node resource", - matcher => '^/nodes/[^/]*$', - GET => { - desc => "Get all the attibutes for the node {noderange}.", - desc1 => "The keyword ALLRESOURCES can be used as {noderange} which means to get node attributes for all the nodes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the attibutes for node \'node1\'.|GET|/nodes/node1|{\n \"node1\":{\n \"profile\":\"compute\",\n \"netboot\":\"xnba\",\n \"arch\":\"x86_64\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\",\n ...\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - PUT => { - desc => "Change the attibutes for the node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Change the attributes mgt=dfm and netboot=yaboot.|PUT|/nodes/node1 {\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - POST => { - desc => "Create the node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: {options:{opt1:v1,opt2:v2},attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Create a node with attributes groups=all, mgt=dfm and netboot=yaboot|POST|/nodes/node1 {\"options\":{\"--template\":\"x86_64kvmguest-template\"}, \"groups\":\"all\",\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||", - cmd => "mkdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the node {noderange}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Delete the node node1|DELETE|/nodes/node1||", - cmd => "rmdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - }, - nodeattr => { - desc => "[URI:/nodes/{noderange}/attrs/{attr1,attr2,attr3 ...}] - The attributes resource for the node {noderange}", - matcher => '^/nodes/[^/]*/attrs/\S+$', - GET => { - desc => "Get the specific attributes for the node {noderange}.", - desc1 => "The keyword ALLRESOURCES can be used as {noderange} which means to get node attributes for all the nodes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the attributes {groups,mgt,netboot} for node node1|GET|/nodes/node1/attrs/groups,mgt,netboot|{\n \"node1\":{\n \"netboot\":\"xnba\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\"\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - PUT_backup => { - desc => "Change attributes for the node {noderange}. DataBody: {attr1:v1,att2:v2,att3:v3 ...}.", - usage => "||An array of node objects.|", - example => "|Get the attributes {groups,mgt,netboot} for node node1|GET|/nodes/node1/attrs/groups;mgt;netboot||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - } - }, - nodestat => { - desc => "[URI:/nodes/{noderange}/nodestat}] - The attributes resource for the node {noderange}", - matcher => '^/nodes/[^/]*/nodestat$', - GET => { - desc => "Get the running status for the node {noderange}.", - usage => "||An object which includes multiple entries like: : { nodestat : }|", - example => "|Get the running status for node node1|GET|/nodes/node1/nodestat|{\n \"node1\":{\n \"nodestat\":\"noping\"\n }\n}|", - cmd => "nodestat", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - }, - nodehost => { - desc => "[URI:/nodes/{noderange}/host] - The mapping of ip and hostname for the node {noderange}", - matcher => '^/nodes/[^/]*/host$', - POST => { - desc => "Create the mapping of ip and hostname record for the node {noderange}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Create the mapping of ip and hostname record for node \'node1\'.|POST|/nodes/node1/host||", - cmd => "makehosts", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, - noderename => { - desc => "[URI:/nodes/{noderange}/rename] - Change old_nodename into new_nodename", - matcher => '^/nodes/[^/]*/rename$', - PUT => { - desc => "Change node name.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Change nodename for node \'node1\'.|PUT|/nodes/node1/rename||", - cmd => "chdef", - fhandler => \&actionhdl, - outhdler => \&defout_remove_appended_info, - }, - }, - nodedns => { - desc => "[URI:/nodes/{noderange}/dns] - The dns record resource for the node {noderange}", - matcher => '^/nodes/[^/]*/dns$', - POST => { - desc => "Create the dns record for the node {noderange}.", - desc1 => "The prerequisite of the POST operation is the mapping of ip and noderange for the node has been added in the /etc/hosts.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Create the dns record for node \'node1\'.|POST|/nodes/node1/dns||", - cmd => "makedns", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the dns record for the node {noderange}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Delete the dns record for node node1|DELETE|/nodes/node1/dns||", - cmd => "makedns", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, - nodedhcp => { - desc => "[URI:/nodes/{noderange}/dhcp] - The dhcp record resource for the node {noderange}", - matcher => '^/nodes/[^/]*/dhcp$', - POST => { - desc => "Create the dhcp record for the node {noderange}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Create the dhcp record for node \'node1\'.|POST|/nodes/node1/dhcp||", - cmd => "makedhcp", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the dhcp record for the node {noderange}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Delete the dhcp record for node node1|DELETE|/nodes/node1/dhcp||", - cmd => "makedhcp", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, - power => { - desc => "[URI:/nodes/{noderange}/power] - The power resource for the node {noderange}", - matcher => '^/nodes/[^/]*/power$', - GET => { - desc => "Get the power status for the node {noderange}.", - usage => "||An object which includes multiple entries like: : { power : }|", - example => "|Get the power status.|GET|/nodes/node1/power|{\n \"node1\":{\n \"power\":\"on\"\n }\n}|", - cmd => "rpower", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT => { - desc => "Change power status for the node {noderange}.", - usage => "|Json Formatted DataBody: {action:on/off/reset ...}.|$usagemsg{non_getreturn}|", - example => "|Change the power status to on|PUT|/nodes/node1/power {\"action\":\"on\"}||", - cmd => "rpower", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - provision => { - desc => "[URI:/nodes/{noderange}/provision] - The deployment resource for the node {noderange}", - matcher => '^/nodes/[^/]*/provision$', - PUT => { - desc => "OS provision for the node {noderange}.", - usage => "|Json Formatted DataBody: {osimage: ubuntu16.04.1-x86_64-install-compute, action: boot}.|$usagemsg{non_getreturn}|", - example => "|Provision the node|PUT|/nodes/node1/provision {\"osimage\":\"ubuntu16.04.1-x86_64-install-compute\"}||", - cmd => "rinstall", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - energy => { - desc => "[URI:/nodes/{noderange}/energy] - The energy resource for the node {noderange}", - matcher => '^/nodes/[^/]*/energy$', - GET => { - desc => "Get all the energy status for the node {noderange}.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the energy attributes.|GET|/nodes/node1/energy|{\n \"node1\":{\n \"cappingmin\":\"272.3 W\",\n \"cappingmax\":\"354.0 W\"\n ...\n }\n}|", - cmd => "renergy", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT => { - desc => "Change energy attributes for the node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: {powerattr:value}.|$usagemsg{non_getreturn}|", - example => "|Turn on the cappingstatus to [on]|PUT|/nodes/node1/energy {\"cappingstatus\":\"on\"}||", - cmd => "renergy", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - energyattr => { - disable => 1, - desc => "[URI:/nodes/{noderange}/energy/{cappingmaxmin,cappingstatus,cappingvalue ...}] - The specific energy attributes resource for the node {noderange}", - matcher => '^/nodes/[^/]*/energy/\S+$', - GET => { - desc => "Get the specific energy attributes cappingmaxmin,cappingstatus,cappingvalue ... for the node {noderange}.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the energy attributes which are specified in the URI.|GET|/nodes/node1/energy/cappingmaxmin,cappingstatus|{\n \"node1\":{\n \"cappingmin\":\"272.3 W\",\n \"cappingmax\":\"354.0 W\"\n }\n}|", - cmd => "renergy", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT_backup => { - desc => "Change energy attributes for the node {noderange}. ", - usage => "|$usagemsg{objchparam} DataBody: {powerattr:value}.|$usagemsg{non_getreturn}|", - example => "|Turn on the cappingstatus to [on]|PUT|/nodes/node1/energy {\"cappingstatus\":\"on\"}||", - cmd => "renergy", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - serviceprocessor => { - disable => 1, - desc => "[URI:/nodes/{noderange}/sp/{community|ip|netmask|...}] - The attribute resource of service processor for the node {noderange}", - matcher => '^/nodes/[^/]*/sp/\S+$', - GET => { - desc => "Get the specific attributes for service processor resource.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the snmp community for the service processor of node1.|GET|/nodes/node1/sp/community|{\n \"node1\":{\n \"SP SNMP Community\":\"public\"\n }\n}|", - cmd => "rspconfig", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT => { - desc => "Change the specific attributes for the service processor resource. ", - usage => "|$usagemsg{objchparam} DataBody: {community:public}.|$usagemsg{non_getreturn}|", - example => "|Set the snmp community to [mycommunity].|PUT|/nodes/node1/sp/community {\"value\":\"mycommunity\"}||", - cmd => "rspconfig", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - macaddress => { - disable => 1, - desc => "[URI:/nodes/{noderange}/mac] - The mac address resource for the node {noderange}", - matcher => '^/nodes/[^/]*/mac$', - GET => { - desc => "Get the mac address for the node {noderange}. Generally, it also updates the mac attribute of the node.", - cmd => "getmacs", - fhandler => \&common, - }, - }, - nextboot => { - desc => "[URI:/nodes/{noderange}/nextboot] - The temporary bootorder resource in next boot for the node {noderange}", - matcher => '^/nodes/[^/]*/nextboot$', - GET => { - desc => "Get the next bootorder.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the bootorder for the next boot. (It's only valid after setting.)|GET|/nodes/node1/nextboot|{\n \"node1\":{\n \"nextboot\":\"Network\"\n }\n}|", - cmd => "rsetboot", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT => { - desc => "Change the next boot order. ", - usage => "|$usagemsg{objchparam} DataBody: {order:net/hd}.|$usagemsg{non_getreturn}|", - example => "|Set the bootorder for the next boot.|PUT|/nodes/node1/nextboot {\"order\":\"net\"}||", - cmd => "rsetboot", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - bootorder => { - desc => "[URI:/nodes/{noderange}/bootorder] - The permanent bootorder resource for the node {noderange}", - matcher => '^/nodes/[^/]*/bootorder$', - GET => { - desc => "Get the permanent boot order.", - usage => "|?|?|", - example => "|Get the permanent bootorder for the node1.|GET|/nodes/node1/bootorder|?|", - cmd => "rbootseq", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT => { - desc => "Change the boot order. DataBody: {\"order\":\"net,hd\"}.", - usage => "|Put data: Json formatted order:value pair.|?|", - example => "|Set the permanent bootorder for the node1.|PUT|/nodes/node1/bootorder|?|", - cmd => "rbootseq", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - vitals => { - desc => "[URI:/nodes/{noderange}/vitals] - The vitals resources for the node {noderange}", - matcher => '^/nodes/[^/]*/vitals$', - GET => { - desc => "Get all the vitals attibutes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the vitails attributes for the node1.|GET|/nodes/node1/vitals|{\n \"node1\":{\n \"SysBrd Fault\":\"0\",\n \"CPUs\":\"0\",\n \"Fan 4A Tach\":\"3330 RPM\",\n \"Drive 15\":\"0\",\n \"SysBrd Vol Fault\":\"0\",\n \"nvDIMM Flash\":\"0\",\n \"Progress\":\"0\"\n ...\n }\n}|", - cmd => "rvitals", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - }, - vitalsattr => { - disable => 1, - desc => "[URI:/nodes/{noderange}/vitals/{temp|voltage|wattage|fanspeed|power|leds...}] - The specific vital attributes for the node {noderange}", - matcher => '^/nodes/[^/]*/vitals/\S+$', - GET => { - desc => "Get the specific vitals attibutes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the \'fanspeed\' vitals attribute.|GET|/nodes/node1/vitals/fanspeed|{\n \"node1\":{\n \"Fan 1A Tach\":\"3219 RPM\",\n \"Fan 4B Tach\":\"2688 RPM\",\n \"Fan 3B Tach\":\"2560 RPM\",\n \"Fan 4A Tach\":\"3330 RPM\",\n \"Fan 2A Tach\":\"3293 RPM\",\n \"Fan 1B Tach\":\"2592 RPM\",\n \"Fan 3A Tach\":\"3182 RPM\",\n \"Fan 2B Tach\":\"2592 RPM\"\n }\n}|", - cmd => "rvitals", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - }, - inventory => { - desc => "[URI:/nodes/{noderange}/inventory] - The inventory attributes for the node {noderange}", - matcher => '^/nodes/[^/]*/inventory$', - GET => { - desc => "Get all the inventory attibutes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the inventory attributes for node1.|GET|/nodes/node1/inventory|{\n \"node1\":{\n \"DIMM 21 \":\"8GB PC3-12800 (1600 MT/s) ECC RDIMM\",\n \"DIMM 1 Manufacturer\":\"Hyundai Electronics\",\n \"Power Supply 2 Board FRU Number\":\"94Y8105\",\n \"DIMM 9 Model\":\"HMT31GR7EFR4C-PB\",\n \"DIMM 8 Manufacture Location\":\"01\",\n \"DIMM 13 Manufacturer\":\"Hyundai Electronics\",\n \"DASD Backplane 4\":\"Not Present\",\n ...\n }\n}|", - cmd => "rinv", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - }, - inventoryattr => { - desc => "[URI:/nodes/{noderange}/inventory/{pci|model...}] - The specific inventory attributes for the node {noderange}", - matcher => '^/nodes/[^/]*/inventory/\S+$', - GET => { - desc => "Get the specific inventory attibutes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the \'model\' inventory attribute for node1.|GET|/nodes/node1/inventory/model|{\n \"node1\":{\n \"System Description\":\"System x3650 M4\",\n \"System Model/MTM\":\"7915C2A\"\n }\n}|", - cmd => "rinv", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - }, - eventlog => { - desc => "[URI:/nodes/{noderange}/eventlog] - The eventlog resource for the node {noderange}", - matcher => '^/nodes/[^/]*/eventlog$', - GET => { - desc => "Get all the eventlog for the node {noderange}.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the eventlog for node1.|GET|/nodes/node1/eventlog|{\n \"node1\":{\n \"eventlog\":[\n \"03/19/2014 15:17:58 Event Logging Disabled, Log Area Reset/Cleared (SEL Fullness)\"\n ]\n }\n}|", - cmd => "reventlog", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - DELETE => { - desc => "Clean up the event log for the node {noderange}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Delete all the event log for node1.|DELETE|/nodes/node1/eventlog|[\n {\n \"eventlog\":[\n \"SEL cleared\"\n ],\n \"name\":\"node1\"\n }\n]|", - cmd => "reventlog", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, - beacon => { - desc => "[URI:/nodes/{noderange}/beacon] - The beacon resource for the node {noderange}", - matcher => '^/nodes/[^/]*/beacon$', - GET_backup => { - desc => "Get the beacon status for the node {noderange}.", - cmd => "rbeacon", - fhandler => \&common, - }, - PUT => { - desc => "Change the beacon status for the node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: {action:on/off/blink}.|$usagemsg{non_getreturn}|", - example => "|Turn on the beacon.|PUT|/nodes/node1/beacon {\"action\":\"on\"}|[\n {\n \"name\":\"node1\",\n \"beacon\":\"on\"\n }\n]|", - cmd => "rbeacon", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, - vm => { - desc => "[URI:/nodes/{noderange}/vm] - The virtualization node {noderange}.", - desc1 => "The node should be a virtual machine of type kvm, esxi ...", - matcher => '^/nodes/[^/]*/vm$', - GET_backup => { - desc => "Get the vm status for the node {noderange}.", - cmd => "lsvm", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT => { - desc => "Change the configuration for the virtual machine {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: \n Set memory size - {\"memorysize\":\"sizeofmemory(MB)\"}\n Add new disk - {\"adddisk\":\"sizeofdisk1(GB),sizeofdisk2(GB)\"}\n Purge disk - {\"purgedisk\":\"scsi_id1,scsi_id2\"}|$usagemsg{non_getreturn}|", - example => "|Set memory to 3000MB.|PUT|/nodes/node1/vm {\"memorysize\":\"3000\"}||", - example1 => "|Add a new 20G disk.|PUT|/nodes/node1/vm {\"adddisk\":\"20G\"}||", - example2 => "|Purge the disk \'hdb\'.|PUT|/nodes/node1/vm {\"purgedisk\":\"hdb\"}||", - cmd => "chvm", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - POST => { - desc => "Create the vm node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: \n Set CPU count - {\"cpucount\":\"numberofcpu\"}\n Set memory size - {\"memorysize\":\"sizeofmemory(MB)\"}\n Set disk size - {\"disksize\":\"sizeofdisk\"}\n Do it by force - {\"force\":\"yes\"}|$usagemsg{non_getreturn}|", - example => "|Create the vm node1 with a 30G disk, 2048M memory and 2 cpus.|POST|/nodes/node1/vm {\"disksize\":\"30G\",\"memorysize\":\"2048\",\"cpucount\":\"2\"}||", - cmd => "mkvm", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the vm node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: \n Purge disk - {\"purge\":\"yes\"}\n Do it by force - {\"force\":\"yes\"}|$usagemsg{non_getreturn}|", - example => "|Remove the vm node1 by force and purge the disk.|DELETE|/nodes/node1/vm {\"force\":\"yes\",\"purge\":\"yes\"}||", - cmd => "rmvm", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, - vmclone => { - desc => "[URI:/nodes/{noderange}/vmclone] - The clone resource for the virtual node {noderange}.", - desc1 => "The node should be a virtual machine of kvm, esxi ...", - matcher => '^/nodes/[^/]*/vmclone$', - POST => { - desc => "Create a clone master from node {noderange}. Or clone the node {noderange} from a clone master.", - usage => "|$usagemsg{objchparam} DataBody: \n Clone a master named \"mastername\" - {\"tomaster\":\"mastername\"}\n Clone a node from master \"mastername\" - {\"frommaster\":\"mastername\"}\n Use Detach mode - {\"detach\":\"yes\"}\n Do it by force - {\"force\":\"yes\"}|The messages of creating Clone target.|", - example1 => "|Create a clone master named \"vmmaster\" from the node1.|POST|/nodes/node1/vmclone {\"tomaster\":\"vmmaster\",\"detach\":\"yes\"}|{\n \"node1\":{\n \"vmclone\":\"Cloning of node1.hda.qcow2 complete (clone uses 9633.19921875 for a disk size of 30720MB)\"\n }\n}|", - example2 => "|Clone the node1 from the clone master named \"vmmaster\".|POST|/nodes/node1/vmclone {\"frommaster\":\"vmmaster\"}||", - cmd => "clonevm", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - }, - vmmigrate => { - desc => "[URI:/nodes/{noderange}/vmmigrate] - The virtualization resource for migration.", - desc1 => "The node should be a virtual machine of kvm, esxi ...", - matcher => '^/nodes/[^/]*/vmmigrate$', - POST => { - desc => "Migrate a node to targe node.", - usage => "|$usagemsg{objchparam} DataBody: {\"target\":\"targethost\"}.", - example => "|Migrate node1 to target host host2.|POST|/nodes/node1/vmmigrate {\"target\":\"host2\"}||", - cmd => "rmigrate", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - }, - updating => { - desc => "[URI:/nodes/{noderange}/updating] - The updating resource for the node {noderange}", - matcher => '^/nodes/[^/]*/updating$', - POST => { - desc => "Update the node with file syncing, software maintenance and rerun postscripts.", - usage => "||An array of messages for performing the node updating.|", - example => "|Initiate an updatenode process.|POST|/nodes/node2/updating|[\n \"There were no syncfiles defined to process. File synchronization has completed.\",\n \"Performing software maintenance operations. This could take a while, if there are packages to install.\n\",\n \"node2: Wed Mar 20 15:01:43 CST 2013 Running postscript: ospkgs\",\n \"node2: Running of postscripts has completed.\"\n]|", - cmd => "updatenode", - fhandler => \&actionhdl, - outhdler => \&infoout, - }, - }, - filesyncing => { - desc => "[URI:/nodes/{noderange}/filesyncing] - The filesyncing resource for the node {noderange}", - matcher => '^/nodes/[^/]*/filesyncing$', - POST => { - desc => "Sync files for the node {noderange}.", - usage => "||An array of messages for performing the file syncing for the node.|", - example => "|Initiate an file syncing process.|POST|/nodes/node2/filesyncing|[\n \"There were no syncfiles defined to process. File synchronization has completed.\"\n]|", - cmd => "updatenode", - fhandler => \&actionhdl, - outhdler => \&infoout, - }, - }, - software_maintenance => { - desc => "[URI:/nodes/{noderange}/sw] - The software maintenance for the node {noderange}", - matcher => '^/nodes/[^/]*/sw$', - POST => { - desc => "Perform the software maintenance process for the node {noderange}.", - usage => "||$usagemsg{objreturn}|", - example => "|Initiate an software maintenance process.|POST|/nodes/node2/sw|{\n \"node2\":[\n \" Wed Apr 3 09:05:42 CST 2013 Running postscript: ospkgs\",\n \" Unable to read consumer identity\",\n \" Postscript: ospkgs exited with code 0\",\n \" Wed Apr 3 09:05:44 CST 2013 Running postscript: otherpkgs\",\n \" ./otherpkgs: no extra rpms to install\",\n \" Postscript: otherpkgs exited with code 0\",\n \" Running of Software Maintenance has completed.\"\n ]\n}|", - cmd => "updatenode", - fhandler => \&actionhdl, - outhdler => \&infoout, - }, - }, - postscript => { - desc => "[URI:/nodes/{noderange}/postscript] - The postscript resource for the node {noderange}", - matcher => '^/nodes/[^/]*/postscript$', - POST => { - desc => "Run the postscripts for the node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: {scripts:[p1,p2,p3,...]}.|$usagemsg{objreturn}|", - example => "|Initiate an updatenode process.|POST|/nodes/node2/postscript {\"scripts\":[\"syslog\",\"remoteshell\"]}|{\n \"node2\":[\n \" Wed Apr 3 09:01:33 CST 2013 Running postscript: syslog\",\n \" Shutting down system logger: [ OK ]\",\n \" Starting system logger: [ OK ]\",\n \" Postscript: syslog exited with code 0\",\n \" Wed Apr 3 09:01:33 CST 2013 Running postscript: remoteshell\",\n \" Stopping sshd: [ OK ]\",\n \" Starting sshd: [ OK ]\",\n \" Postscript: remoteshell exited with code 0\",\n \" Running of postscripts has completed.\"\n ]\n}|", - cmd => "updatenode", - fhandler => \&actionhdl, - outhdler => \&infoout, - }, - }, - nodeshell => { - desc => "[URI:/nodes/{noderange}/nodeshell] - The nodeshell resource for the node {noderange}", - matcher => '^/nodes/[^/]*/nodeshell$', - POST => { - desc => "Run the command in the shell of the node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: set environment {ENV:{en1:v1,en2:v2}}, raw command {raw:[op1,op2]}, direct command {command:[cmd1,cmd2]}.|$usagemsg{objreturn}|", - example => "|Run the \'date\' command on the node2.|POST|/nodes/node2/nodeshell {\"command\":[\"date\",\"ls\"]}|{\n \"node2\":[\n \" Wed Apr 3 08:30:26 CST 2013\",\n \" testline1\",\n \" testline2\"\n ]\n}|Use ENV and raw command on the node2.|POST|/nodes/node2/nodeshell {\"ENV\":{\"DSH_REMOTE_PASSWORD\":\"cluster\",\"DSH_FROM_USERID\":\"root\",\"DSH_TO_USERID\":\"root\"},\"raw\":[\"-K\"]}|[\n \"/usr/bin/ssh setup is complete.\",\n \"return code = 0\"\n]|", - cmd => "xdsh", - fhandler => \&actionhdl, - outhdler => \&infoout, - }, - }, - nodecopy => { - desc => "[URI:/nodes/{noderange}/nodecopy] - The nodecopy resource for the node {noderange}", - matcher => '^/nodes/[^/]*/nodecopy$', - POST => { - desc => "Copy files to the node {noderange}.", - usage => "|$usagemsg{objchparam} DataBody: {src:[file1,file2],target:dir}.|$usagemsg{non_getreturn}|", - example => "|Copy files /tmp/f1 and /tmp/f2 from xCAT MN to the node2:/tmp.|POST|/nodes/node2/nodecopy {\"src\":[\"/tmp/f1\",\"/tmp/f2\"],\"target\":\"/tmp\"}|no output for succeeded copy.|", - cmd => "xdcp", - fhandler => \&actionhdl, - outhdler => \&infoout, - }, - }, - subnodes => { - desc => "[URI:/nodes/{noderange}/subnodes] - The sub-nodes resources for the node {noderange}", - matcher => '^/nodes/[^/]*/subnodes$', - GET => { - desc => "Return the Children nodes for the node {noderange}.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the children nodes for node \'node1\'.|GET|/nodes/node1/subnodes|{\n \"cmm01node09\":{\n \"mpa\":\"ngpcmm01\",\n \"parent\":\"ngpcmm01\",\n \"serial\":\"1035CDB\",\n \"mtm\":\"789523X\",\n \"cons\":\"fsp\",\n \"hwtype\":\"blade\",\n \"objtype\":\"node\",\n \"groups\":\"blade,all,p260\",\n \"mgt\":\"fsp\",\n \"nodetype\":\"ppc,osi\",\n \"slotid\":\"9\",\n \"hcp\":\"10.1.9.9\",\n \"id\":\"1\"\n },\n ...\n}|", - cmd => "rscan", - fhandler => \&actionhdl, - outhdler => \&defout, - }, +#turn on or off the debugging output +my $DEBUGGING = 0; +my $VERSION = "2.8"; - # the put should be implemented by customer that using GET to get all the resources and define it with PUT /nodes/ - PUT_bak => { - desc => "Update the Children node for the node {noderange}.", - cmd => "rscan", - fhandler => \&common, - }, - }, - bootstate => { - desc => "[URI:/nodes/{noderange}/bootstate] - The boot state resource for node {noderange}.", - matcher => '^/nodes/[^/]*/bootstate$', - GET => { - desc => "Get boot state.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the next boot state for the node1.|GET|/nodes/node1/bootstate|{\n \"node1\":{\n \"bootstat\":\"boot\"\n }\n}|", - cmd => "nodeset", - fhandler => \&actionhdl, - outhdler => \&actionout, - }, - PUT => { - desc => "Set the boot state.", - usage => "|$usagemsg{objchparam} DataBody: {osimage:xxx}/{state:offline}.|$usagemsg{non_getreturn}|", - example => "|Set the next boot state for the node1.|PUT|/nodes/node1/bootstate {\"osimage\":\"rhels6.4-x86_64-install-compute\"}||", - cmd => "nodeset", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, +my $q = CGI->new; +my $url = $q->url; +my $pathInfo = $q->path_info; +my $requestType = $ENV{'REQUEST_METHOD'}; +my $queryString = $ENV{'QUERY_STRING'}; +my %queryhash; +my @path = split(/\//, $pathInfo); +shift(@path); +my $resource = $path[0]; +my $pageContent = ''; +my $request = {clienttype => 'ws'}; - # TODO: rflash - }, - - #### definition for group resources - groups => { - all_groups => { - desc => "[URI:/groups] - The group list resource.", - desc1 => "This resource can be used to display all the groups which have been defined in the xCAT database.", - matcher => '^/groups$', - GET => { - desc => "Get all the groups in xCAT.", - desc1 => "The attributes details for the group will not be displayed.", - usage => "||Json format: An array of group names.|", - example => "|Get all the group names from xCAT database.|GET|/groups|[\n \"__mgmtnode\",\n \"all\",\n \"compute\",\n \"ipmi\",\n \"kvm\",\n]|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout_remove_appended_type, - } - }, - group_allattr => { - desc => "[URI:/groups/{groupname}] - The group resource", - matcher => '^/groups/[^/]*$', - GET => { - desc => "Get all the attibutes for the group {groupname}.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the attibutes for group \'all\'.|GET|/groups/all|{\n \"all\":{\n \"members\":\"zxnode2,nodexxx,node1,node4\"\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - PUT => { - desc => "Change the attibutes for the group {groupname}.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Change the attributes mgt=dfm and netboot=yaboot.|PUT|/groups/all {\"mgt\":\"dfm\",\"netboot\":\"yaboot\"}||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - }, - group_attr => { - desc => "[URI:/groups/{groupname}/attrs/{attr1,attr2,attr3 ...}] - The attributes resource for the group {groupname}", - matcher => '^/groups/[^/]*/attrs/\S+$', - GET => { - desc => "Get the specific attributes for the group {groupname}.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the attributes {mgt,netboot} for group all|GET|/groups/all/attrs/mgt,netboot|{\n \"all\":{\n \"netboot\":\"yaboot\",\n \"mgt\":\"dfm\"\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - }, - }, - - #### definition for services resources: dns, dhcp, hostname - services => { - host => { - desc => "[URI:/services/host] - The hostname resource.", - matcher => '^/services/host$', - POST => { - desc => "Create the ip/hostname records for all the nodes to /etc/hosts.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Create the ip/hostname records for all the nodes to /etc/hosts.|POST|/services/host||", - cmd => "makehosts", - fhandler => \&nonobjhdl, - outhdler => \&noout, - } - }, - dns => { - desc => "[URI:/services/dns] - The dns service resource.", - matcher => '^/services/dns$', - POST => { - desc => "Initialize the dns service.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Initialize the dns service.|POST|/services/dns||", - cmd => "makedns", - fhandler => \&nonobjhdl, - outhdler => \&noout, - } - }, - bmcdiscover => { - desc => "[URI:/services/bmcdiscover] - The bmc which does support nmap in the xCAT cluster.", - matcher => '^/services/bmcdiscover/[^/]+$', - GET => { - desc => "Get all the bmc alive.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the bmc which do not support slp in the network.|", - cmd => "bmcdiscover", - fhandler => \&bmclisthdl, - outhdler => \&defout_remove_appended_info, - - } - }, - checkbmcauth => { - desc => "[URI:/services/checkbmcauth] - Check if bmc user or password is correct.", - matcher => '^/services/checkbmcauth/[^/]*/[^/]+$', - GET => { - desc => "Check if bmc user or password is correct.", - usage => "||$usagemsg{objreturn}|", - example => "|Check bmc user or password.|GET|/services/checkbmcauth||", - cmd => "bmcdiscover", - fhandler => \&bmccheckhdl, - outhdler => \&defout_remove_appended_info, - - } - }, - getbmcipsource => { - desc => "[URI:/services/getbmcipsource] - Get BMC IP Address source.", - matcher => '^/services/getbmcipsource/[^/]*/[^/]+$', - GET => { - desc => "Get BMC IP Address source.", - usage => "||$usagemsg{objreturn}|", - example => "|Get BMC IP Address source.|GET|/services/getbmcipsource||", - cmd => "bmcdiscover", - fhandler => \&bmccheckhdl, - outhdler => \&defout_remove_appended_info, - - } - }, - - dhcp => { - desc => "[URI:/services/dhcp] - The dhcp service resource.", - matcher => '^/services/dhcp$', - POST => { - desc => "Create the dhcpd.conf for all the networks which are defined in the xCAT Management Node.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Create the dhcpd.conf and restart the dhcpd.|POST|/services/dhcp||", - cmd => "makedhcp", - fhandler => \&nonobjhdl, - outhdler => \&noout, - } - }, - - # todo: for slpnode, we need use the query attribute to specify the network parameter for lsslp command - slpnodes => { - desc => "[URI:/services/slpnodes] - The nodes which support SLP in the xCAT cluster", - matcher => '^/services/slpnodes', - GET => { - desc => "Get all the nodes which support slp protocol in the network.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the nodes which support slp in the network.|GET|/services/slpnodes|{\n \"ngpcmm01\":{\n \"mpa\":\"ngpcmm01\",\n \"otherinterfaces\":\"10.1.9.101\",\n \"serial\":\"100037A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"2\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"5c:f3:fc:25:da:99\"\n },\n ...\n}|", - cmd => "lsslp", - fhandler => \&nonobjhdl, - outhdler => \&defout, - }, - PUT_bakcup => { - desc => "Update the discovered nodes to database.", - cmd => "lsslp", - fhandler => \&common, - }, - }, - specific_slpnodes => { - desc => "[URI:/services/slpnodes/{CEC|FRAME|MM|IVM|RSA|HMC|CMM|IMM2|FSP...}] - The slp nodes with specific service type in the xCAT cluster", - matcher => '^/services/slpnodes/[^/]*$', - GET => { - desc => "Get all the nodes with specific slp service type in the network.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the CMM nodes which support slp in the network.|GET|/services/slpnodes/CMM|{\n \"ngpcmm01\":{\n \"mpa\":\"ngpcmm01\",\n \"otherinterfaces\":\"10.1.9.101\",\n \"serial\":\"100037A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"2\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"5c:f3:fc:25:da:99\"\n },\n \"Server--SNY014BG27A01K\":{\n \"mpa\":\"Server--SNY014BG27A01K\",\n \"otherinterfaces\":\"10.1.9.106\",\n \"serial\":\"100CF0A\",\n \"mtm\":\"789392X\",\n \"hwtype\":\"cmm\",\n \"side\":\"1\",\n \"objtype\":\"node\",\n \"nodetype\":\"mp\",\n \"groups\":\"cmm,all,cmm-zet\",\n \"mgt\":\"blade\",\n \"hidden\":\"0\",\n \"mac\":\"34:40:b5:df:0a:be\"\n }\n}|", - cmd => "lsslp", - fhandler => \&nonobjhdl, - outhdler => \&defout, - }, - PUT_backup => { - desc => "Update the discovered nodes to database.", - cmd => "lsslp", - fhandler => \&common, - }, - }, - #### definition for mknb [-c] - nbimage => { - desc => "[URI:/services/nbimage] - Create netboot root image for specified arch.", - matcher => '^/services/nbimage/arch/[ppc64|x86_64]', - POST => { - desc => "creates a network boot root image", - usage => "|$usagemsg{objchparam} DataBody: {\"onlyconfigfile\":\"[true|yes|Y|1]|[false|no|N|0]\"}.|$usagemsg{non_getreturn}|", - example => "|Create a network boot root iamge for the specified arch|", - cmd => "mknb", - fhandler => \&actionhdl, - }, - }, - console => { - desc => "[URI:/services/console] - Conserver configuration on management node.", - matcher => '^/services/console$', - PUT => { - desc => "Update conserver configuration", - usage => "|Json Formatted DataBody: {nodes: [node1, node2], action: on/off trust_host: }.|$usagemsg{non_getreturn}|", - example => "|Enable the console capability for node1|PUT|/services/console {\"nodes\":\n[\"node1\", \"node2\"]\"\n, \"action\": \"on\", \n\"trust_host\": \"host\"}||", - cmd => "makeconservercf", - fhandler => \&actionhdl, - outhdler => \&noout, - } - }, - }, - - #### definition for network resources - networks => { - allnetwork => { - desc => "[URI:/networks] - The network list resource.", - desc1 => "This resource can be used to display all the networks which have been defined in the xCAT database.", - matcher => '^\/networks$', - GET => { - desc => "Get all the networks in xCAT.", - desc1 => "The attributes details for the networks will not be displayed.", - usage => "||Json format: An array of networks names.|", - example => "|Get all the networks names from xCAT database.|GET|/networks|[\n \"network1\",\n \"network2\",\n \"network3\",\n]|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout_remove_appended_type, - }, - POST => { - desc => "Create the networks resources base on the network configuration on xCAT MN.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Create the networks resources base on the network configuration on xCAT MN.|POST|/networks||", - cmd => "makenetworks", - fhandler => \&actionhdl, - outhdler => \&noout, - }, - }, - network_allattr => { - desc => "[URI:/networks/{netname}] - The network resource", - matcher => '^\/networks\/[^\/]*$', - GET => { - desc => "Get all the attibutes for the network {netname}.", - desc1 => "The keyword ALLRESOURCES can be used as {netname} which means to get network attributes for all the networks.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the attibutes for network \'network1\'.|GET|/networks/network1|{\n \"network1\":{\n \"gateway\":\"\",\n \"mask\":\"255.255.255.0\",\n \"mgtifname\":\"eth2\",\n \"net\":\"10.0.0.0\",\n \"tftpserver\":\"10.0.0.119\",\n ...\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - PUT => { - desc => "Change the attibutes for the network {netname}.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Change the attributes mgtifname=eth0 and net=10.1.0.0.|PUT|/networks/network1 {\"mgtifname\":\"eth0\",\"net\":\"10.1.0.0\"}||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - POST => { - desc => "Create the network {netname}. DataBody: {attr1:v1,att2:v2...}.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Create a network with attributes gateway=10.1.0.1, mask=255.255.0.0 |POST|/networks/network1 {\"gateway\":\"10.1.0.1\",\"mask\":\"255.255.0.0\"}||", - cmd => "mkdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the network {netname}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Delete the network network1|DELETE|/networks/network1||", - cmd => "rmdef", - fhandler => \&defhdl, - outhdler => \&noout - }, - }, - network_attr => { - desc => "[URI:/networks/{netname}/attrs/attr1,attr2,...] - The attributes resource for the network {netname}", - matcher => '^\/networks\/[^\/]*/attrs/\S+$', - GET => { - desc => "Get the specific attributes for the network {netname}.", - desc1 => "The keyword ALLRESOURCES can be used as {netname} which means to get network attributes for all the networks.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the attributes {groups,mgt,netboot} for network network1|GET|/networks/network1/attrs/gateway,mask,mgtifname,net,tftpserver|{\n \"network1\":{\n \"gateway\":\"9.114.34.254\",\n \"mask\":\"255.255.255.0\",\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - PUT__backup => { - desc => "Change attributes for the network {netname}. DataBody: {attr1:v1,att2:v2,att3:v3 ...}.", - usage => "||An array of network objects.|", - example => "|Get the attributes {gateway,mask,mgtifname,net,tftpserver} for networks network1|GET|/networks/network1/attrs/gateway;mask;net||", - cmd => "chdef", - fhandler => \&noout, - } - }, - - }, - - #### definition for osimage resources - osimages => { - osimage => { - desc => "[URI:/osimages] - The osimage resource.", - matcher => '^\/osimages$', - GET => { - desc => "Get all the osimage in xCAT.", - usage => "||Json format: An array of osimage names.|", - example => "|Get all the osimage names.|GET|/osimages|[\n \"sles11.2-x86_64-install-compute\",\n \"sles11.2-x86_64-install-iscsi\",\n \"sles11.2-x86_64-install-iscsiibft\",\n \"sles11.2-x86_64-install-service\"\n]|", - - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout_remove_appended_type, - }, - POST => { - desc => "Create the osimage resources base on the parameters specified in the Data body.", - - #usage => "|$usagemsg{objchparam} DataBody: {iso:isoname\\file:filename\\node:noderange,params:[{attr1:value1,attr2:value2}]}|$usagemsg{non_getreturn}|", - usage => "|$usagemsg{objchparam} DataBody: {iso:isoname\\file:filename,params:[{attr1:value1,attr2:value2}]}|$usagemsg{non_getreturn}|", - example1 => "|Create osimage resources based on the ISO specified|POST|/osimages {\"iso\":\"/iso/RHEL6.4-20130130.0-Server-ppc64-DVD1.iso\"}||", - example2 => "|Create osimage resources based on an xCAT image or configuration file|POST|/osimages {\"file\":\"/tmp/sles11.2-x86_64-install-compute.tgz\"}||", - - # TD: the imgcapture need to be moved to nodes/.*/osimages - # example3 => "|Create a image based on the specified Linux diskful node|POST|/osimages {\"node\":\"rhcn1\"}||", - cmd => "copycds", - fhandler => \&imgophdl, - outhdler => \&noout, - }, - }, - osimage_allattr => { - desc => "[URI:/osimages/{imgname}] - The osimage resource", - matcher => '^\/osimages\/[^\/]*$', - GET => { - desc => "Get all the attibutes for the osimage {imgname}.", - desc1 => "The keyword ALLRESOURCES can be used as {imgname} which means to get image attributes for all the osimages.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the attributes for the specified osimage.|GET|/osimages/sles11.2-x86_64-install-compute|{\n \"sles11.2-x86_64-install-compute\":{\n \"provmethod\":\"install\",\n \"profile\":\"compute\",\n \"template\":\"/opt/xcat/share/xcat/install/sles/compute.sles11.tmpl\",\n \"pkglist\":\"/opt/xcat/share/xcat/install/sles/compute.sles11.pkglist\",\n \"osvers\":\"sles11.2\",\n \"osarch\":\"x86_64\",\n \"osname\":\"Linux\",\n \"imagetype\":\"linux\",\n \"otherpkgdir\":\"/install/post/otherpkgs/sles11.2/x86_64\",\n \"osdistroname\":\"sles11.2-x86_64\",\n \"pkgdir\":\"/install/sles11.2/x86_64\"\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - - POST => { - desc => "Create the osimage {imgname}.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2]|$usagemsg{non_getreturn}|", - example => "|Create a osimage obj with the specified parameters.|POST|/osimages/sles11.3-ppc64-install-compute {\"osvers\":\"sles11.3\",\"osarch\":\"ppc64\",\"osname\":\"Linux\",\"provmethod\":\"install\",\"profile\":\"compute\"}||", - cmd => "mkdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - PUT => { - desc => "Change the attibutes for the osimage {imgname}.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2...}|$usagemsg{non_getreturn}|", - example => "|Change the 'osvers' and 'osarch' attributes for the osiamge.|PUT|/osimages/sles11.2-ppc64-install-compute/ {\"osvers\":\"sles11.3\",\"osarch\":\"x86_64\"}||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the osimage {imgname}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Delete the specified osimage.|DELETE|/osimages/sles11.3-ppc64-install-compute||", - cmd => "rmdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - }, - osimage_attr => { - desc => "[URI:/osimages/{imgname}/attrs/attr1,attr2,attr3 ...] - The attributes resource for the osimage {imgname}", - matcher => '^\/osimages\/[^\/]*/attrs/\S+$', - GET => { - desc => "Get the specific attributes for the osimage {imgname}.", - desc1 => "The keyword ALLRESOURCES can be used as {imgname} which means to get image attributes for all the osimages.", - usage => "||Json format: An array of attr:value pairs for the specified osimage.|", - example => "|Get the specified attributes.|GET|/osimages/sles11.2-ppc64-install-compute/attrs/imagetype,osarch,osname,provmethod|{\n \"sles11.2-ppc64-install-compute\":{\n \"provmethod\":\"install\",\n \"osname\":\"Linux\",\n \"osarch\":\"ppc64\",\n \"imagetype\":\"linux\"\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - - # TD, the implementation may need to be change. - PUT_backup => { - desc => "Change the attibutes for the osimage {imgname}.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,attr2:v2...}|$usagemsg{non_getreturn}|", - example => "|Change the 'osvers' and 'osarch' attributes for the osiamge.|PUT|/osimages/sles11.2-ppc64-install-compute/attrs/osvers;osarch {\"osvers\":\"sles11.3\",\"osarch\":\"x86_64\"}||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - - }, - osimage_op => { - desc => "[URI:/osimages/{imgname}/instance] - The instance for the osimage {imgname}", - matcher => '^\/osimages\/[^\/]*/instance$', - POST => { - desc => "Operate the instance of the osimage {imgname}.", - usage => "|$usagemsg{objchparam} DataBody: {action:gen\\pack\\export,params:[{attr1:value1,attr2:value2...}]}|$usagemsg{non_getreturn}|", - example1 => "|Generates a stateless image based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"gen\"}||", - example2 => "|Packs the stateless image from the chroot file system based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"pack\"}||", - example3 => "|Exports an xCAT image based on the specified osimage|POST|/osimages/sles11.2-x86_64-install-compute/instance {\"action\":\"export\"}||", - cmd => "", - fhandler => \&imgophdl, - }, - DELETE => { - desc => "Delete the stateless or statelite image instance for the osimage {imgname} from the file system", - usage => "||$usagemsg{non_getreturn}", - example => "|Delete the stateless image for the specified osimage|DELETE|/osimages/sles11.2-x86_64-install-compute/instance||", - cmd => "rmimage", - fhandler => \&imgophdl, - }, - }, - - # todo: genimage, packimage, imagecapture, imgexport, imgimport - }, - - #### definition for policy resources - policy => { - policy => { - desc => "[URI:/policy] - The policy resource.", - matcher => '^\/policy$', - GET => { - desc => "Get all the policies in xCAT.", - desc1 => "It will dislplay all the policy resource.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the policy objects.|GET|/policy|[\n \"1\",\n \"1.2\",\n \"2\",\n \"4.8\"\n]|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout_remove_appended_type, - }, - }, - policy_allattr => { - desc => "[URI:/policy/{policy_priority}] - The policy resource", - matcher => '^\/policy\/[^\/]*$', - GET => { - desc => "Get all the attibutes for a policy {policy_priority}.", - desc1 => "It will display all the policy attributes for one policy resource.", - desc2 => "The keyword ALLRESOURCES can be used as {policy_priority} which means to get policy attributes for all the policies.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the attribute for policy 1.|GET|/policy/1|{\n \"1\":{\n \"name\":\"root\",\n \"rule\":\"allow\"\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - PUT => { - desc => "Change the attibutes for the policy {policy_priority}.", - desc1 => "It will change one or more attributes for a policy.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Set the name attribute for policy 3.|PUT|/policy/3 {\"name\":\"root\"}||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - POST => { - desc => "Create the policy {policyname}. DataBody: {attr1:v1,att2:v2...}.", - desc1 => "It will creat a new policy resource.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Create a new policy 10.|POST|/policy/10 {\"name\":\"root\",\"commands\":\"rpower\"}||", - cmd => "chdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the policy {policy_priority}.", - desc1 => "Remove one or more policy resource.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Delete the policy 10.|DELETE|/policy/10||", - cmd => "rmdef", - fhandler => \&defhdl, - outhdler => \&noout, - }, - }, - policy_attr => { - desc => "[URI:/policy/{policyname}/attrs/{attr1,attr2,attr3,...}] - The attributes resource for the policy {policy_priority}", - matcher => '^\/policy\/[^\/]*/attrs/\S+$', - GET => { - desc => "Get the specific attributes for the policy {policy_priority}.", - desc1 => "It will get one or more attributes of a policy.", - desc2 => "The keyword ALLRESOURCES can be used as {policy_priority} which means to get policy attributes for all the policies.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the name and rule attributes for policy 1.|GET|/policy/1/attrs/name,rule|{\n \"1\":{\n \"name\":\"root\",\n \"rule\":\"allow\"\n }\n}|", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - }, - }, - #### definition for global setting resources - globalconf => { - all_site => { - desc => "[URI:/globalconf] - The global configuration resource.", - desc1 => "This resource can be used to display all the global configuration which have been defined in the xCAT database.", - matcher => '^\/globalconf$', - GET => { - desc => "Get all the xCAT global configuration.", - desc1 => "It will display all the global attributes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get all the global configuration|GET|/globalconf|{\n \"clustersite\":{\n \"xcatconfdir\":\"/etc/xcat\",\n \"tftpdir\":\"/tftpboot\",\n ...\n }\n}|", - cmd => "lsdef", - fhandler => \&sitehdl, - outhdler => \&defout, - }, - POST_backup => { - desc => "Add the site attributes. DataBody: {attr1:v1,att2:v2...}.", - desc1 => "One or more global attributes could be added/modified.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Add one or more attributes to xCAT database|POST|/globalconf {\"domain\":\"cluster.com\",\"mydomain\":\"mycluster.com\"}||", - cmd => "chdef", - fhandler => \&sitehdl, - }, - }, - site => { - desc => "[URI:/globalconf/attrs/{attr1,attr2 ...}] - The specific global configuration resource.", - matcher => '^\/globalconf/attrs/\S+$', - GET => { - desc => "Get the specific configuration in global.", - desc1 => "It will display one or more global attributes.", - usage => "||$usagemsg{objreturn}|", - example => "|Get the \'master\' and \'domain\' configuration.|GET|/globalconf/attrs/master,domain|{\n \"clustersite\":{\n \"domain\":\"cluster.com\",\n \"master\":\"192.168.1.15\"\n }\n}|", - cmd => "lsdef", - fhandler => \&sitehdl, - outhdler => \&defout, - }, - PUT => { - desc => "Change the global attributes.", - desc1 => "It can be used for changing/adding global attributes.", - usage => "|$usagemsg{objchparam} DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => "|Change/Add the domain attribute.|PUT|/globalconf/attrs/domain {\"domain\":\"cluster.com\"}||", - cmd => "chdef", - fhandler => \&sitehdl, - outhdler => \&noout, - }, - POST_backup => { - desc => "Create the global configuration entry. DataBody: {name:value}.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Create the domain attribute|POST|/globalconf/attrs/domain {\"domain\":\"cluster.com\"}|?|", - cmd => "chdef", - fhandler => \&sitehdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Remove the site attributes.", - desc1 => "Used for femove one or more global attributes.", - usage => "||$usagemsg{non_getreturn}|", - example => "|Remove the domain configure.|DELETE|/globalconf/attrs/domain||", - cmd => "chdef", - fhandler => \&sitehdl, - outhdler => \&noout, - }, - }, - }, - - #### definition for database/table resources - tables => { - table_nodes => { - desc => "[URI:/tables/{tablelist}/nodes/{noderange}] - The node table resource", - desc1 => "For a large number of nodes, this API call can be faster than using the corresponding nodes resource. The disadvantage is that you need to know the table names the attributes are stored in.", - matcher => '^/tables/[^/]+/nodes/[^/]+$', - GET => { - desc => "Get attibutes of tables for a noderange.", - usage => "||An object containing each table. Within each table object is an array of node objects containing the attributes.|", - example1 => qq(|Get all the columns from table nodetype for node1 and node2.|GET|/tables/nodetype/nodes/node1,node2|{\n \"nodetype\":[\n {\n \"provmethod\":\"rhels6.4-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"provmethod\":\"rhels6.3-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|), - example2 => qq(|Get all the columns from tables nodetype and noderes for node1 and node2.|GET|/tables/nodetype,noderes/nodes/node1,node2|{\n \"noderes\":[\n {\n \"installnic\":\"mac\",\n \"netboot\":\"xnba\",\n \"name\":\"node1\",\n \"nfsserver\":\"192.168.1.15\"\n },\n {\n \"installnic\":\"mac\",\n \"netboot\":\"pxe\",\n \"name\":\"node2\",\n \"proxydhcp\":\"no\"\n }\n ],\n \"nodetype\":[\n {\n \"provmethod\":\"rhels6.4-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"provmethod\":\"rhels6.3-x86_64-install-compute\",\n \"profile\":\"compute\",\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|), - fhandler => \&tablenodehdl, - outhdler => \&tableout, - }, - PUT => { - desc => "Change the node table attibutes for {noderange}.", - usage => "|A hash of table names and attribute objects. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|", - example => '|Change the nodetype.arch and noderes.netboot attributes for nodes node1,node2.|PUT|/tables/nodetype,noderes/nodes/node1,node2 {"nodetype":{"arch":"x86_64"},"noderes":{"netboot":"xnba"}}||', - fhandler => \&tablenodeputhdl, - outhdler => \&noout, - }, - }, - table_nodes_attrs => { - desc => "[URI:/tables/{tablelist}/nodes/nodes/{noderange}/{attrlist}] - The node table attributes resource", - desc1 => "For a large number of nodes, this API call can be faster than using the corresponding nodes resource. The disadvantage is that you need to know the table names the attributes are stored in.", - matcher => '^/tables/[^/]+/nodes/[^/]+/[^/]+$', - GET => { - desc => "Get table attibutes for a noderange.", - usage => "||An object containing each table. Within each table object is an array of node objects containing the attributes.|", - example => qq(|Get OS and ARCH attributes from nodetype table for node1 and node2.|GET|/tables/nodetype/nodes/node1,node2/os,arch|{\n \"nodetype\":[\n {\n \"arch\":\"x86_64\",\n \"name\":\"node1\",\n \"os\":\"rhels6.4\"\n },\n {\n \"arch\":\"x86_64\",\n \"name\":\"node2\",\n \"os\":\"rhels6.3\"\n }\n ]\n}|), - fhandler => \&tablenodehdl, - outhdler => \&tableout, - }, - PUT_backup => { - desc => "[URI:/tables/nodes/{noderange}] - Change the node table attibutes for the {noderange}.", - usage => "|A hash of table names and attribute objects. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|", - example => '|Change the nodehm.mgmt and noderes.netboot attributes for nodes node1-node5.|PUT|/tables/nodes/node1-node5 {"nodehm":{"mgmt":"ipmi"},"noderes":{"netboot":"xnba"}}||', - fhandler => \&tablenodeputhdl, - outhdler => \&noout, - }, - }, - table_all_rows => { - desc => "[URI:/tables/{tablelist}/rows] - The non-node table resource", - desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.", - matcher => '^/tables/[^/]+/rows$', - GET => { - desc => "Get all rows from non-node tables.", - usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|", - example => qq(|Get all rows from networks table.|GET|/tables/networks/rows|{\n \"networks\":[\n {\n \"netname\":\"192_168_13_0-255_255_255_0\",\n \"gateway\":\"192.168.13.254\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.13.0\",\n \"mask\":\"255.255.255.0\"\n },\n {\n \"netname\":\"192_168_12_0-255_255_255_0\",\n \"gateway\":\"192.168.12.254\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.12.0\",\n \"mask\":\"255.255.255.0\"\n },\n ]\n}|), - fhandler => \&tablerowhdl, - outhdler => \&tableout, - }, - }, - table_rows => { - desc => "[URI:/tables/{tablelist}/rows/{keys}] - The non-node table rows resource", - desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.", - desc2 => "{keys} should be the name=value pairs which are used to search table. e.g. {keys} should be [net=192.168.1.0,mask=255.255.255.0] for networks table query since the net and mask are the keys of networks table.", - matcher => '^/tables/[^/]+/rows/[^/]+$', - GET => { - desc => "Get attibutes for rows from non-node tables.", - usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|", - example => qq(|Get row which net=192.168.1.0,mask=255.255.255.0 from networks table.|GET|/tables/networks/rows/net=192.168.1.0,mask=255.255.255.0|{\n \"networks\":[\n {\n \"mgtifname\":\"eth0\",\n \"netname\":\"192_168_1_0-255_255_255_0\",\n \"tftpserver\":\"192.168.1.15\",\n \"gateway\":\"192.168.1.100\",\n \"staticrangeincrement\":\"1\",\n \"net\":\"192.168.1.0\",\n \"mask\":\"255.255.255.0\"\n }\n ]\n}|), - fhandler => \&tablerowhdl, - outhdler => \&tableout, - }, - PUT => { - desc => "Change the non-node table attibutes for the row that matches the {keys}.", - usage => "|A hash of attribute names and values. DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - example => '|Create a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet {"net":"10.0.1.0","mask":"255.255.255.0","gateway":"10.0.1.254","ifname":"eth1"}||', - fhandler => \&tablerowputhdl, - outhdler => \&noout, - }, - DELETE => { - desc => "Delete rows from a non-node table that have the attribute values specified in {keys}.", - usage => "||$usagemsg{non_getreturn}|", - example => '|Delete a route row which routename=privnet in the routes table.|DELETE|/tables/routes/rows/routename=privnet||', - fhandler => \&tablerowdelhdl, - outhdler => \&noout, - }, - }, - table_rows_attrs => { - desc => "[URI:/tables/{tablelist}/rows/{keys}/{attrlist}] - The non-node table attributes resource", - desc1 => "Use this for tables that don't have node name as the key of the table, for example: passwd, site, networks, polciy, etc.", - matcher => '^/tables/[^/]+/rows/[^/]+/[^/]+$', - GET => { - desc => "Get specific attibutes for rows from non-node tables.", - usage => "||An object containing each table. Within each table object is an array of row objects containing the attributes.|", - example => qq(|Get attributes mgtifname and tftpserver which net=192.168.1.0,mask=255.255.255.0 from networks table.|GET|/tables/networks/rows/net=192.168.1.0,mask=255.255.255.0/mgtifname,tftpserver|{\n \"networks\":[\n {\n \"mgtifname\":\"eth0\",\n \"tftpserver\":\"192.168.1.15\"\n }\n ]\n}|), - fhandler => \&tablerowhdl, - outhdler => \&tableout, - }, - }, - }, - - #### definition for tokens resources - tokens => { - tokens => { - desc => "[URI:/tokens] - The authentication token resource.", - matcher => '^\/tokens', - POST => { - desc => "Create a token.", - usage => "||An array of all the global configuration list.|", - example => "|Aquire a token for user \'root\'.|POST|/tokens {\"userName\":\"root\",\"userPW\":\"cluster\"}|{\n \"token\":{\n \"id\":\"a6e89b59-2b23-429a-b3fe-d16807dd19eb\",\n \"expire\":\"2014-3-8 14:55:0\"\n }\n}|", - fhandler => \&nonobjhdl, - outhdler => \&tokenout, - }, - POST_backup => { - desc => "Add the site attributes. DataBody: {attr1:v1,att2:v2...}.", - usage => "|?|?|", - example => "|?|?|?|?|", - cmd => "chdef", - fhandler => \&sitehdl, - }, - }, - }, - - ### interface to access local system resource which is not managed by xcat directly - ### localres can be looked as a top level non-xcat resource pool - ### rest operation will trasfer the target resource to xcatd plugin to handle the non-xcat resource - localres => { - localres => { - desc => "[URI:/localres/*] - The local non-xcat resource.", - matcher => '^/localres(/[^/]*)+$', - GET => { - desc => "List information for the target system resource.", - usage => "||For target resource can match any resource type which can be proccssed by the resthelper plugin.|", - example => qq(|List adapters on MN machine|GET|/localres/interface/|{\n \"interfaces\":[\n\"eth0\",\n \"eth1\",\n]"|), - cmd => "localrest", - fhandler => \&localreshdl, - outhdler => \&localresout, - }, - } - }, - - templates => { - node => { - desc => - "[URI:/templates/node] - The template information of nodes.", - matcher => '^/templates/node$', - GET => { - desc => "Show attributes of a node template.", - usage => "||$usagemsg{objreturn}|", - example => "|GET all the attibutes of node template \'x86_64kvmguest-template\'.|GET|/templates/node {\"options\":{\"--template\":\"x86_64kvmguest-template\"}} |{\n \"arch\":{\n \"x86_64\":\"compute\",\n \"bmc\":\"MANDATORY:The hostname or ip address of the BMC adapater\",\n \bmcpassword\":\"MANDATORY:the password of the BMC\",\n \"mgt\":\"ipmi\",\n \"groups\":\"all\",\n ...\n }\n}", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout, - }, - }, - # Generally, the 'oprions' json filed could be used to support different argument of the command. - # As limited by the different outhdler, a new resource name 'all' has to be added here. - all => { - desc => "[URI:/templates/node/all] - The template information of node.", - matcher => '^/templates/node/all$', - GET => { - desc => "List template items of node.", - usage => "||$usagemsg{objreturn}|", - example => "|List all the templates. |GET /templates/node/all {\"options\":{\"--template\":\"\"}}| [cec-template,hmc-template,ppc64le-template,x86_64-template,x86_64kvmguest-template]", - cmd => "lsdef", - fhandler => \&defhdl, - outhdler => \&defout_remove_appended_type, - }, - }, - }, -); - -# supported formats -my %formatters = ( - 'json' => \&wrapJson, - - #'html' => \&wrapHtml, - #'xml' => \&wrapXml -); - -# error status codes +#error status codes my $STATUS_BAD_REQUEST = "400 Bad Request"; my $STATUS_UNAUTH = "401 Unauthorized"; my $STATUS_FORBIDDEN = "403 Forbidden"; @@ -1316,1845 +41,21 @@ my $STATUS_EXPECT_FAILED = "417 Expectation Failed"; my $STATUS_TEAPOT = "418 I'm a teapot"; my $STATUS_SERVICE_UNAVAILABLE = "503 Service Unavailable"; -# good status codes +#good status codes my $STATUS_OK = "200 OK"; my $STATUS_CREATED = "201 Created"; -# Development notes: -# - added this line to /etc/httpd/conf/httpd.conf to hide the cgi-bin and .cgi extension in the uri: -# ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi -# - also upgraded CGI to 3.52 -# - If "Internal Server Error" is returned, look at /var/log/httpd/ssl_error_log -# - can run your cgi script from the cli: http://perldoc.perl.org/CGI.html#DEBUGGING +#default format +my $format = 'html'; -# This is how the parameters come in: -# GET: url parameters come $q->url_param. There is no put/post data. -# PUT: url parameters come $q->url_param. Put data comes in q->param(PUTDATA). -# POST: url parameters come $q->url_param. Post data comes in q->param(POSTDATA). -# DELETE: ?? - -# Notes from http://perldoc.perl.org/CGI.html: -# %params = $q->Vars; # same as $q->param() except put it in a hash -# @foo = split("\0",$params{'foo'}); -# my $error = $q->cgi_error; #todo: check for errors that occurred while processing user input -# print $q->end_html; #todo: add the tags -# $q->url_param() # gets url options, even when there is put/post data (unlike q->param) - - - -#### Main procedure to handle the REST request - -# To get the HTTP elements through perl CGI module -my $q = CGI->new; -my $pathInfo = $q->path_info; # the resource specification, i.e. everything in the url after xcatws -my $requestType = $q->request_method(); # GET, PUT, POST, PATCH, DELETE -my $userAgent = $q->user_agent(); # the client program: curl, etc. -my @path = split(/\//, $pathInfo); # The uri path like /nodes/node1/... - -# Define the golbal variables which will be used through the handling process -my $pageContent = ''; # Global var containing the ouptut back to the rest client -my %header_info; #Global var containing the extra info to the http header -my $request = { clienttype => 'ws' }; # Global var that holds the request to send to xcatd -my $format = 'json'; # The output format for a request invoke -my $xmlinstalled; # Global var to speicfy whether the xml modules have been loaded - -# To easy the perl debug, this script can be run directly with 'perl -d' -# This script also support to generate the rest api doc automatically. -# Following part of code will not be run when this script is called by http server -my $dbgdata; -sub dbgusage { print "Usage:\n $0 -h\n $0 -g rst > ../../docs/source/advanced/restapi/restapi_resource/restapi_reference.rst (generate document)\n $0 {GET|PUT|POST|DELETE} URI user:password \'{data}\'\n"; } - -if ($ARGV[0] eq "-h") { - dbgusage(); - exit 0; -} elsif ($ARGV[0] eq "-g") { - - # generate the document - require genrestapidoc; - if (defined($ARGV[1])) { - genrestapidoc::gendoc(\%URIdef, $ARGV[1]); - } else { - genrestapidoc::gendoc(\%URIdef); - } - exit 0; -} elsif ($ARGV[0] eq "-d") { - displayUsage(); - exit 0; -} elsif ($ARGV[0] =~ /(GET|PUT|POST|DELETE)/) { - - # parse the parameters when run this script locally - $requestType = $ARGV[0]; - $pathInfo = $ARGV[1]; - - unless ($pathInfo) { dbgusage(); exit 1; } - - if ($ARGV[2] =~ /(.*):(.*)/) { - $ENV{userName} = $1; - $ENV{password} = $2; - } else { - dbgusage(); - exit 0; - } - $dbgdata = $ARGV[3] if defined($ARGV[3]); -} elsif (defined($ARGV[0])) { - dbgusage(); - exit 1; -} - -my $JSON; # global ptr to the json object. Its set by loadJSON() - -# Since the json is the only supported format, load it at beginning -# need to do this early, so we can fetch the PUT/POST params -loadJSON(); - -# the input parameters from both the url and put/post data will be combined and then -# separated into the general params (not specific to the api call) and params specific to the call -# Note: some of the values of the params in the hash can be arrays -# $generalparams - the general parameters like 'debug=1', 'pretty=1' -# $paramhash - all parameters that come from the url or put/post data except the ones that are put in $generalparams -my ($generalparams, $paramhash) = fetchParameters(); - -my $DEBUGGING = $generalparams->{debug}; # turn on or off the debugging output by setting debug=1 (or 2) in the url string -if ($DEBUGGING) { - displaydebugmsg(); -} - -# The filter flag is used to group the nodes which have the same output -my $XCOLL = $generalparams->{xcoll}; - -# Process the format requested -$format = $generalparams->{format} if (defined($generalparams->{format})); - -# Remove the last '/' in the pathInfo -$pathInfo =~ s/\/$//; - -# Get the payload format from the end of URI -#if ($pathInfo =~ /\.json$/) { -# $format = "json"; -# $pathInfo =~ s/\.json$//; -#} elsif ($pathInfo =~ /\.json.pretty$/) { -# $format = "json"; -# $pretty = 1; -# $pathInfo =~ s/\.json.pretty$//; -#} elsif ($pathInfo =~ /\.xml$/) { -# $format = "xml"; -# $pathInfo =~ s/\.xml$//; -#} elsif ($pathInfo =~ /\.html$/) { -# $format = "html"; -# $pathInfo =~ s/\.html$//; -#} - -#if (!exists $formatters{$format}) { -# error("The format '$format' is not supported",$STATUS_BAD_REQUEST); -#} - -if ($format eq 'json') { - - # make the output to be readable if 'pretty=1' is specified - if ($generalparams->{pretty}) { $JSON->indent(1); } -} - -# we need XML all the time to send request to xcat, even if thats not the return format requested by the user -loadXML(); - -# The first layer of resource URI. It should be 'nodes' for URI '/nodes/node1' -my $uriLayer1; - -# Get all the layers in the URI -my @layers = split('\/', $pathInfo); -shift(@layers); - -if ($#layers < 0) { - - # If no resource was specified, list all the resource groups which have been defined in the %URIdef - my $json; - foreach (sort keys %URIdef) { - push @{$json}, $_; - } - if ($json) { - addPageContent($JSON->encode($json)); - } - sendResponseMsg($STATUS_OK); # this will also exit -} else { - $uriLayer1 = $layers[0]; -} - -# set the user and password to access xcatd -$request->{becomeuser}->[0]->{username}->[0] = $ENV{userName} if (defined($ENV{userName})); -$request->{becomeuser}->[0]->{username}->[0] = $generalparams->{userName} if (defined($generalparams->{userName})); -$request->{becomeuser}->[0]->{password}->[0] = $ENV{password} if (defined($ENV{password})); -$request->{becomeuser}->[0]->{password}->[0] = $generalparams->{userPW} if (defined($generalparams->{userPW})); - -# use the token if it is specified with X_AUTH_TOKEN head -$request->{tokens}->[0]->{tokenid}->[0] = $ENV{'HTTP_X_AUTH_TOKEN'} if (defined($ENV{'HTTP_X_AUTH_TOKEN'})); - -# find and invoke the correct handler and output handler functions -my $outputdata; -my $handled; -if (defined($URIdef{$uriLayer1})) { - - # Make sure the resource has been defined - foreach my $res (keys %{ $URIdef{$uriLayer1} }) { - my $matcher = $URIdef{$uriLayer1}->{$res}->{matcher}; - if ($pathInfo =~ m|$matcher|) { - - # matched to a resource - unless (defined($URIdef{$uriLayer1}->{$res}->{$requestType})) { - error("request method '$requestType' is not supported on resource '$pathInfo'", $STATUS_NOT_ALLOWED); - } - if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{fhandler})) { - my $params; - - $params->{'cmd'} = $URIdef{$uriLayer1}->{$res}->{$requestType}->{cmd} if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{cmd})); - $params->{'outputhdler'} = $URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler} if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler})); - $params->{'layers'} = \@layers; - $params->{'resourcegroup'} = $uriLayer1; - $params->{'resourcename'} = $res; - - # Call the handler subroutine which specified in 'fhandler' to send request to xcatd and get the response - $outputdata = $URIdef{$uriLayer1}->{$res}->{$requestType}->{fhandler}->($params); - - # Filter the output data from the response - $outputdata = filterData($outputdata); - - # Restructure the output data with the subroutine which is specified in 'outhdler' - if (defined($URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler})) { - $outputdata = $URIdef{$uriLayer1}->{$res}->{$requestType}->{outhdler}->($outputdata, $params); - } else { - - # Call the appropriate formatting function stored in the formatters hash as default output handler - if (exists $formatters{$format}) { - $formatters{$format}->($outputdata); - } - } - - $handled = 1; - last; - } - } - } -} else { - - # not matches to any resource group. Check the 'resource group' to improve the performance - error("Unspported resource.", $STATUS_NOT_FOUND); -} - -# the URI cannot match to any resources which are defined in %URIdef -unless ($handled) { - error("Unspported resource.", $STATUS_NOT_FOUND); -} - - -# all output has been added into the global varibale pageContent, call the response funcion to generate HTTP reply and exit - -if (isPost()) { - sendResponseMsg($STATUS_CREATED); -} -else { - sendResponseMsg($STATUS_OK); -} - -#### End of the Main Program - - - - - -#=========================================================== -# Subrutines -sub isGET { return uc($requestType) eq "GET"; } -sub isPost { return uc($requestType) eq "POST"; } -sub isPut { return uc($requestType) eq "PUT"; } -sub isPatch { return uc($requestType) eq "PATCH"; } -sub isDelete { return uc($requestType) eq "DELETE"; } - - -#handle the output for def command and rscan -#handle the input like -# ===raw xml input -# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n' -# $d->{data}->[msg list] -# -# ===msg format -# Object name: -# attr=value -#OR -# : -# attr=value -# --- -#TO -# --- -# { : { -# attr : value -# ... -# } ... } -sub defout { - my $data = shift; - - my $json; - foreach my $d (@$data) { - my $nodename; - my $lines; - my @alldata; - if (defined($d->{info})) { - foreach (@{ $d->{info} }) { - push @alldata, split('\n', $_); - } - $lines = \@alldata; - } elsif (defined($d->{data})) { - foreach (@{ $d->{data} }) { - push @alldata, split('\n', $_); - } - $lines = \@alldata; - } - foreach my $l (@$lines) { - if ($l =~ /No responses/) { # handle the case that no output from lsslp command - return; - } elsif ($l =~ /Could not find any object definitions/) { - $json->{info} = $l; - last; - } - if ($l =~ /^Object name: / || $l =~ /^\S+:$/) { # start new node - if ($l =~ /^Object name:\s+(\S+)/) { # handle the output of lsdef -t - $nodename = $1; - } - if ($l =~ /^(\S+):$/) { # handle the output for stanza format '-z' - $nodename = $1; - } - } - else { # just an attribute of the current node - if (!$nodename) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); } - my ($attr, $val) = $l =~ /^\s*(\S+?)=(.*)$/; - if (!defined($attr)) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); } - $json->{$nodename}->{$attr} = $val; - } - } - } - if ($json) { - addPageContent($JSON->encode($json), 1); - } -} - -#handle the output for lsdef -t command -#handle the input like -# ===raw xml input -# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n' -# -# ===msg format -# node1 (node) -# node2 (node) -# node3 (node) -# --- -#TO -# --- -# node1 -# node2 -# node3 -sub defout_remove_appended_type { - my $data = shift; - - my $json; - foreach my $d (@$data) { - my $jsonnode; - my $lines = $d->{info}; - foreach my $l (@$lines) { - if ($l =~ /^(\S*)\s+\(.*\)$/) { # start new node - push @{$json}, $1; - } elsif ($l =~ /Could not find any object definitions/) { - push @{$json}, $l; - last; - } - } - } - if ($json) { - addPageContent($JSON->encode($json), 1); - } -} - -#handle the output for bmcdiscover command -#handle the input like -# -#$VAR1 = [ -# { -# 'info' => [ -# 'bmc_1' -# ] -# }, -# { -# 'info' => [ -# 'bmc_2' -# ] -# }, -# { -# 'info' => [ -# 'bmc_3' -# ] -# } -# ]; -# -# ===msg format -# bmc_1 -# bmc_2 -# bmc_3 -# --- -# -#TO -# --- -# [ -# "bmc_1", -# "bmc_2", -# "bmc_3" -# ] - -# -sub defout_remove_appended_info { - my $data = shift; - - my $json; - foreach my $d (@$data) { - my $jsonnode; - my $lines = $d->{info}; - foreach my $l (@$lines) { - - # if ($l =~ /^(\S*)\s+\(.*\)$/) { # start new node - push(@{$json}, $l); - - # } - } - } - if ($json) { - addPageContent($JSON->encode($json), 1); - } -} - - -sub localresout { - my $data = shift; - my $json; - if ($data->[0]->{info}->[0] eq 'stream') { - $format = 'stream'; - $header_info{'attachment'} = $data->[0]->{info}->[1]; - addPageContent($data->[0]->{info}->[2]); - } elsif ($data->[0]->{info}->[0] eq 'json') { - addPageContent($data->[0]->{info}->[1]); - } -} - -# hanlde the output which has the node irrelevant message (e.g. the output for updatenode command) -# handle the input like -# ===raw xml input -# $d->{info}->[msg list] - each msg could be mulitple msg which split with '\n' -# $d->{data}->[msg list] -# $d->{data}->{contents}->[msg list] -# -# ===msg format -# "There were no syncfiles defined to process. File synchronization has completed.", -# "Performing software maintenance operations. This could take a while, if there are packages to install.", -# "node2: Tue Apr 2 15:55:57 CST 2013 Running postscript: ospkgs", -# --- -#TO -# --- -# [ -# "There were no syncfiles defined to process. File synchronization has completed.", -# "Performing software maintenance operations. This could take a while, if there are packages to install.", -# "node2: Tue Apr 2 15:55:57 CST 2013 Running postscript: ospkgs", -# ] -# -# An exception is to handle the output of 'xdsh'(nodeshell). Since each msg has a : head, split the head out and group -# the msg with the name in the head. - -sub infoout { - my $data = shift; - my $param = shift; - - my $json; - foreach my $d (@$data) { - if (defined($d->{info})) { - foreach (@{ $d->{info} }) { - push @{$json}, split('\n', $_); - } - } - if (defined($d->{data})) { - if (ref($d->{data}->[0]) ne "HASH") { - foreach (@{ $d->{data} }) { - push @{$json}, split('\n', $_); - } - } else { - if (defined($d->{data}->[0]->{contents})) { - push @{$json}, @{ $d->{data}->[0]->{contents} }; - } - } - } - if (defined($d->{error})) { - push @{$json}, @{ $d->{error} }; - } - } - - # for nodeshell (xdsh), group msg with node name - if ($param->{'resourcename'} =~ /(nodeshell|postscript|software_maintenance)/) { - my $jsonnode; - foreach (@{$json}) { - if (/^(\S+):(.*)$/) { - push @{ $jsonnode->{$1} }, $2 if ($2 !~ /^\s*$/); - } - } - if (!$jsonnode && $json) - { - push(@{$jsonnode}, @{$json}); - } - addPageContent($JSON->encode($jsonnode), 1); - return; - } - if ($json) { - addPageContent($JSON->encode($json), 1); - } -} - -# hanlde the output which is node relevant (rpower, rinv, rvitals ...) -# the output must be grouped with 'node' as key -# handle the input like -# ===raw xml input -# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg -# $d->{node}->{data}->[msg] -#OR -# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg -# $d->{node}->{data}->{contents}->[msg] -#OR -# $d->{node}->{name}->[name] # this is must have, otherwise ignore the msg -# $d->{node}->{data}->{contents}->[msg] -# $d->{node}->{data}->{desc}->[msg] -# -# Note: if does not have '$d->{node}->{data}->{desc}', use the resource name as the name of attribute. -# e.g. Get /node/node1/power, the record is '"power":"off"' -# -# ===msg format -# -# -# 1.41 (VVE128GUS 2013/07/22) -# UEFI Version -# -# node1 -# -# --- -#TO -# --- -# { -# "node1":{ -# "UEFI Version":"1.41 (VVE128GUS 2013/07/22)", -# } -# } -sub actionout { - my $data = shift; - my $param = shift; - - my $jsonnode; - foreach my $d (@$data) { - unless (defined($d->{node}->[0]->{name})) { - next; - } - if (defined($d->{node}->[0]->{data}) && (ref($d->{node}->[0]->{data}->[0]) ne "HASH" || !defined($d->{node}->[0]->{data}->[0]->{contents}))) { - - # no $d->{node}->{data}->{contents} or $d->{node}->[0]->{data} is not hash - $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $param->{'resourcename'} } = $d->{node}->[0]->{data}->[0]; - } elsif (defined($d->{node}->[0]->{data}->[0]->{contents})) { - if (defined($d->{node}->[0]->{data}->[0]->{desc})) { - - # has $d->{node}->{data}->{desc} - $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $d->{node}->[0]->{data}->[0]->{desc}->[0] } = $d->{node}->[0]->{data}->[0]->{contents}->[0]; - } else { - - # use resourcename as the record name - if ($param->{'resourcename'} eq "eventlog") { - push @{ $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $param->{'resourcename'} } }, $d->{node}->[0]->{data}->[0]->{contents}->[0]; - } elsif ($param->{'resourcename'} =~ /(vitals|inventory)/) { - - # handle output of rvital and rinv for ppc node - #push @{$jsonnode->{$d->{node}->[0]->{name}->[0]}}, $d->{node}->[0]->{data}->[0]->{contents}->[0]; - push @{ $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{Message} }, $d->{node}->[0]->{data}->[0]->{contents}->[0]; - } else { - $jsonnode->{ $d->{node}->[0]->{name}->[0] }->{ $param->{'resourcename'} } = $d->{node}->[0]->{data}->[0]->{contents}->[0]; - } - } - } - } - - addPageContent($JSON->encode($jsonnode), 1) if ($jsonnode); -} - -# hanlde the output which has the token id -# handle the input like -# ===raw xml input -# $d->{data}->{token}->{id} -# $d->{data}->{token}->{expire} -sub tokenout { - my $data = shift; - - my $json; - foreach my $d (@$data) { - if (defined($d->{data}) && defined($d->{data}->[0]->{token})) { - $json->{token}->{id} = $d->{data}->[0]->{token}->[0]->{id}->[0]; - $json->{token}->{expire} = $d->{data}->[0]->{token}->[0]->{expire}->[0]; - } - } - - if ($json) { - addPageContent($JSON->encode($json)); - } -} - -# This is the general callback subroutine for PUT/POST/DELETE methods -# when this subroutine is called, that means the operation has been done successfully -# The correct output is 'null' -sub noout { - return; -### for debugging - my $data = shift; - - addPageContent(qq(\n\n\n=======================================================\nDebug: Following message is just for debugging. It will be removed in the GAed version.\n)); - - my $json; - if ($data) { - addPageContent($JSON->encode($data)); - } - - addPageContent(qq(["Debug: the operation has been done successfully"])); -### finish the debugging -} - -# The operation callback subroutine for def related resource (lsdef, chdef ...) -# assembe the xcat request, send it to xcatd and get response -sub defhdl { - my $params = shift; - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # set the command name - $request->{command} = $params->{'cmd'}; - - # push the -t args for *def command - my $resrctype = $params->{'resourcegroup'}; - $resrctype =~ s/s$//; # remove the last 's' as the type of object - push @args, ('-t', $resrctype) if $resrctype ne 'template'; - - # push the object name - node/noderange - if (defined($urilayers[1]) && $resrctype ne 'template') { - if ($urilayers[1] eq "ALLRESOURCES") { - unless (isGET()) { - error("Keyword ALLRESOURCES is only supported for GET Action.", $STATUS_NOT_FOUND); - } - push @args, '-l'; - } else { - push @args, ('-o', $urilayers[1]); - } - } - - # For template only. - if ($resrctype eq 'template') { - if ($params->{'resourcename'} eq "all") { - $paramhash->{'options'}->{'-a'} = ""; - } - } - # For the put/post which specifies attributes like mgt=ipmi groups=all - foreach my $k (keys(%$paramhash)) { - next if (!$k); - # NOTE: The json field 'options' may be confilict with the attibute - # name called 'options', but it does not happen currently. A better - # solution is to add a new json field called attributes like this - # {options:{}, attributes:{}} to avoid of the ambiguity. - if ($k eq 'options') { - my $options = $paramhash->{$k}; - my ($opt_key, $opt_val); - while(($opt_key, $opt_val) = each(%{$options})) { - next if (!$opt_key || grep (/^$opt_key$/, ('-o','-l','-t'))); - push @args, $opt_key; - push @args, $opt_val if $opt_val; - } - next; - } - push @args, "$k=$paramhash->{$k}" if $paramhash->{$k}; - } - - if ($params->{'resourcename'} eq "allnode") { - push @args, '-s'; - } elsif ($params->{'resourcename'} =~ /(nodeattr|osimage_attr|group_attr|policy_attr|network_attr)/) { - - # if /nodes/node1/attrs/attr1,att2 is specified, for get request, - # use 'lsdef -i' to specify the attribute list - my $attrs = $urilayers[3]; - $attrs =~ s/;/,/g; - - if (isGET()) { - push @args, ('-i', $attrs); - } - } - - push @{ $request->{arg} }, @args; - my $req = genRequest(); - my $responses = sendRequest($req); - - return $responses; -} - -# The operation callback subroutine for any node related resource (power, energy ...) -# assembe the xcat request, send it to xcatd and get response -sub actionhdl { - my $params = shift; - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # set the command name - $request->{command} = $params->{'cmd'}; - - # push the object name - node/noderange - if (defined($urilayers[1])) { - $request->{noderange} = $urilayers[1]; - } - - if ($params->{'resourcename'} eq "power") { - if (isGET()) { - push @args, 'stat'; - } elsif ($paramhash->{'action'}) { - - #my @v = keys(%$paramhash); - push @args, $paramhash->{'action'}; - } else { - error("Missed Action.", $STATUS_NOT_FOUND); - } - } elsif ($params->{'resourcename'} =~ /(energy|energyattr)/) { - if (isGET()) { - if ($params->{'resourcename'} eq "energy") { - push @args, 'all'; - } elsif ($params->{'resourcename'} eq "energyattr") { - my @attrs = split(',', $urilayers[3]); - push @args, @attrs; - } - } elsif ($paramhash) { - my @params = keys(%$paramhash); - push @args, "$params[0]=$paramhash->{$params[0]}"; - } else { - error("Missed Action.", $STATUS_NOT_FOUND); - } - } elsif ($params->{'resourcename'} eq "bootstate") { - if (isGET()) { - push @args, 'stat'; - } elsif ($paramhash->{'action'}) { - push @args, $paramhash->{'action'}; - } elsif ($paramhash) { - my @params = keys(%$paramhash); - if ($params[0] eq "state") { - - # hanlde the {state:offline} - push @args, $paramhash->{ $params[0] }; - } else { - - # handle the {osimage:imagename} - push @args, "$params[0]=$paramhash->{$params[0]}"; - } - } else { - error("Missed Action.", $STATUS_NOT_FOUND); - } - } elsif ($params->{'resourcename'} eq "nextboot") { - if (isGET()) { - push @args, 'stat'; - } elsif ($paramhash->{'order'}) { - push @args, $paramhash->{'order'}; - } else { - error("Missed Action.", $STATUS_NOT_FOUND); - } - } elsif ($params->{'resourcename'} =~ /(vitals|vitalsattr|inventory|inventoryattr)/) { - if (defined($urilayers[3])) { - my @attrs = split(';', $urilayers[3]); - push @args, @attrs; - } else { # default, get all attrs - push @args, "all"; - } - } elsif ($params->{'resourcename'} eq "serviceprocessor") { - if (isGET()) { - push @args, $urilayers[3]; - } elsif (isPut() or isPost()) { - if ($paramhash->{'value'} and defined($urilayers[3])) { - push @args, $urilayers[3] . "=" . $paramhash->{'value'}; - } else { - foreach my $key (keys %$paramhash) { - if (($key ne '') and (exists($paramhash->{$key}))) { - push @args, $key . "=" . $paramhash->{$key}; - } - } - } - } - } elsif ($params->{'resourcename'} eq "eventlog") { - if (isGET()) { - push @args, 'all'; - } elsif (isDelete()) { - push @args, 'clear'; - } - } elsif ($params->{'resourcename'} eq "beacon") { - if (isPut()) { - push @args, $paramhash->{'action'}; - } - } elsif ($params->{'resourcename'} eq "filesyncing") { - push @args, '-F'; - } elsif ($params->{'resourcename'} eq "software_maintenance") { - push @args, '-S'; - } elsif ($params->{'resourcename'} eq "postscript") { - push @args, '-P'; - if (defined($paramhash->{'scripts'})) { - push @args, join(',', @{ $paramhash->{'scripts'} }); - } - } elsif ($params->{'resourcename'} eq "nodeshell") { - if (%$paramhash) - { - foreach my $key1 (keys %$paramhash) { - if ($key1 eq "ENV" && defined($paramhash->{'ENV'})) { - foreach my $key (keys %{ $paramhash->{'ENV'} }) { - if (($key ne '') and (exists($paramhash->{'ENV'}->{$key}))) { - push(@{ $request->{env} }, "$key=$paramhash->{'ENV'}->{$key}"); - } - } - next; - } - elsif ($key1 eq "raw" && defined($paramhash->{'raw'})) { - if (ref($paramhash->{'raw'}) eq "ARRAY") { - push @args, join(';', @{ $paramhash->{'raw'} }); - } else { - push @args, $paramhash->{'raw'}; - } - next; - } - elsif ($key1 eq "command" && defined($paramhash->{'command'})) { - if (ref($paramhash->{'command'}) eq "ARRAY") { - push @args, join(';', @{ $paramhash->{'command'} }); - } else { - push @args, $paramhash->{'command'}; - } - next; - } - } - } - else { - error("Lack of operation data.", $STATUS_BAD_REQUEST, 3); - } - - } elsif ($params->{'resourcename'} eq "nodecopy") { - if (defined($paramhash->{'src'})) { - push @args, @{ $paramhash->{'src'} }; - } - if (defined($paramhash->{'target'})) { - push @args, $paramhash->{'target'}; - } - } elsif ($params->{'resourcename'} =~ /(dns|dhcp)/) { - if (isDelete()) { - push @args, '-d'; - } - } elsif ($params->{'resourcename'} eq "subnodes") { - if (isGET()) { - push @args, '-z'; - } - } elsif ($params->{'resourcename'} eq "vm") { - - # handle the virtual machine - if (isGET()) { - - # do nothing for kvm and esxi - } elsif (isPut()) { # change the configuration of vm - if (defined($paramhash->{'adddisk'})) { #add new disk - push @args, ('-a', $paramhash->{'adddisk'}); - } - - #if (defined ($paramhash->{'rmdisk'})) { #remove disk - # push @args, ('-d', $paramhash->{'rmdisk'}); - #} - if (defined($paramhash->{'purgedisk'})) { #purge disk - push @args, ('-p', $paramhash->{'purgedisk'}); - } - if (defined($paramhash->{'resizedisk'})) { #change the disk size - $paramhash->{'resizedisk'} =~ s/\:/=/; # replace : to be = in the param - push @args, ('--resize', $paramhash->{'resizedisk'}); - } - if (defined($paramhash->{'memorysize'})) { #change the memory size - push @args, ('--mem', $paramhash->{'memorysize'}); - } - if (defined($paramhash->{'cpucount'})) { #change the cpu size - push @args, ('--cpus', $paramhash->{'cpucount'}); - } - } elsif (isPost()) { # create virtual machine - if (defined($paramhash->{'master'})) { # specify the master node for clone - push @args, ('-m', $paramhash->{'master'}); - } - if (defined($paramhash->{'disksize'})) { # specify disk size - push @args, ('-s', $paramhash->{'disksize'}); - } - if (defined($paramhash->{'memorysize'})) { #specify the memory size - push @args, ('--mem', $paramhash->{'memorysize'}); - } - if (defined($paramhash->{'cpucount'})) { #specify the cpu size - push @args, ('--cpus', $paramhash->{'cpucount'}); - } - if (defined($paramhash->{'force'}) && $paramhash->{'force'} eq "yes") { # force the recreate - push @args, "-f"; - } - } elsif (isDelete()) { - if (defined($paramhash->{'force'}) && $paramhash->{'force'} eq "yes") { # force the recreate - push @args, "-f"; - } - if (defined($paramhash->{'purge'}) && $paramhash->{'purge'} eq "yes") { # purge disk when remove the vm - push @args, "-p"; - } - } - } elsif ($params->{'resourcename'} eq "vmclone") { - - # handle the clone of virtual machine - if (isPost()) { - if (defined($paramhash->{'tomaster'})) { - push @args, ("-t", $paramhash->{'tomaster'}); - } elsif (defined($paramhash->{'frommaster'})) { - push @args, ("-b", $paramhash->{'frommaster'}); - } else { - error("Lack of operation data.", $STATUS_BAD_REQUEST, 3); - } - - if (defined($paramhash->{'detach'}) && $paramhash->{'detach'} eq "yes") { - push @args, "-d"; - } - if (defined($paramhash->{'force'}) && $paramhash->{'force'} eq "yes") { # force the recreate - push @args, "-f"; - } - } - } elsif (($params->{'resourcename'} eq "vmmigrate")) { - - # handle the migration of virtual machine - if (isPost()) { - if (defined($paramhash->{'target'})) { - push @args, $paramhash->{'target'}; - } else { - error("Lack of operation data.", $STATUS_BAD_REQUEST, 3); - } - } - } elsif ($params->{'resourcename'} eq "noderename") { - - if (isPut()) { - if (defined($paramhash->{'newNode'})) { #specify the new name for node - push @args, ('-t', "node"); - push @args, ('-o', $urilayers[1]); - push @args, ('-n', $paramhash->{'newNode'}); - } - } - } elsif ($params->{'resourcename'} eq "nbimage") { - delete $request->{noderange}; - push @args, $urilayers[3]; - if (isPost()) { - if (defined($paramhash->{'onlyconfigfile'})) { - my $tmp_value = $paramhash->{'onlyconfigfile'}; - if ($tmp_value =~ /true|yes|Y|1/i) { - push @args, "-c"; - } elsif ($tmp_value !~ /false|no|N|0/i) { - error("Option value \"$tmp_value\" invalid.", $STATUS_BAD_REQUEST, 3); - } - } - } - - } elsif ($params->{'resourcename'} eq "console") { - delete $request->{noderange}; - if ($paramhash->{'action'}) { - my %action = ('on' => '', 'off' => '-d'); - push @args, $action{$paramhash->{'action'}}; - if ($paramhash->{'nodes'}) { - $request->{noderange} = join(',', @{$paramhash->{'nodes'}}); - } else { - error("Missed node.") - } - } - if ($paramhash->{'trust_host'}) { - push @args, '-t'; - push @args, $paramhash->{'trust_host'}; - } - } elsif ($params->{'resourcename'} eq "provision") { - if ($paramhash->{'osimage'}) { - push @args, 'osimage='.$paramhash->{'osimage'}; - } elsif ($paramhash->{'action'}) { - push @args, $paramhash->{'action'}; - } - } - - push @{ $request->{arg} }, @args; - my $req = genRequest(); - my $responses = sendRequest($req); - - return $responses; -} - -sub localreshdl { - my $params = shift; - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # set the command name - $request->{command} = $params->{'cmd'}; - - if (isGET() && scalar(@urilayers) > 1 && $urilayers[-1] eq "detail") { - push @args, "show"; - } elsif (isGET() && scalar(@urilayers) > 1 && $urilayers[-1] eq "file") { - push @args, "download"; - } elsif (isGET()) { - push @args, "list"; - } elsif (isPost()) { - push @args, "create"; - } elsif (isPut()) { - push @args, "update"; - } elsif (isDelete()) { - push @args, "delete"; - } - shift @urilayers; - foreach my $item (@urilayers) { - push @args, $item if $item ne 'detail' && $item ne 'file'; - } - push @{ $request->{arg} }, @args; - - # localrest is single plugin handler, use sequntial to avoid of multi-level processes - $request->{'sequential'}->[0] = 1; - my $req = genRequest(); - my $responses = sendRequest($req); - return $responses; -} - -# The operation callback subroutine for node irrelevant commands like makedns -n and makedhcp -n -# assembe the xcat request, send it to xcatd and get response -sub nonobjhdl { - my $params = shift; - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # set the command name - $request->{command} = $params->{'cmd'}; - if ($params->{'resourcename'} =~ /(dns|dhcp)/) { - push @args, '-n'; - } elsif ($params->{'resourcename'} eq "slpnodes") { - if (isGET()) { - push @args, '-z'; - } - } elsif ($params->{'resourcename'} eq "specific_slpnodes") { - if (isGET()) { - push @args, "-z"; - push @args, "-s"; - push @args, $urilayers[2]; - } - } elsif ($params->{'resourcename'} eq "tokens") { - $request->{gettoken}->[0]->{username}->[0] = $generalparams->{userName} if (defined($generalparams->{userName})); - $request->{gettoken}->[0]->{password}->[0] = $generalparams->{userPW} if (defined($generalparams->{userPW})); - } - - push @{ $request->{arg} }, @args; - my $req = genRequest(); - my $responses = sendRequest($req); - - return $responses; -} - - -# operate image instance for a osimage -sub imgophdl { - my $params = shift; - my @args = (); - if (isPost()) { - if ($params->{'resourcename'} eq "osimage_op") { - my $action = $paramhash->{'action'}; - unless ($action) { - error("Missed Action.", $STATUS_NOT_FOUND); - } elsif ($action eq "gen") { - $params->{'cmd'} = "genimage"; - } elsif ($action eq "pack") { - $params->{'cmd'} = "packimage"; - } elsif ($action eq "export") { - $params->{'cmd'} = "imgexport"; - } else { - error("Incorrect action:$action.", $STATUS_BAD_REQUEST); - } - } elsif ($params->{'resourcename'} eq "osimage") { - if (exists($paramhash->{'iso'})) { - $params->{'cmd'} = "copycds"; - push @{ $params->{layers} }, $paramhash->{'iso'}; - } elsif (exists($paramhash->{'file'})) { - $params->{'cmd'} = "imgimport"; - push @{ $params->{layers} }, $paramhash->{'file'}; - } elsif (exists($paramhash->{'node'})) { - $params->{'cmd'} = "imgcapture"; - - #push @{$params->{layers}}, $paramhash->{'node'}; - push @{ $request->{noderange} }, $paramhash->{'node'}; - } else { - error("Invalid source.", $STATUS_NOT_FOUND); - } - } - } - $request->{command} = $params->{'cmd'}; - push @args, $params->{layers}->[1]; - if (exists($paramhash->{'params'})) { - foreach (keys %{ $paramhash->{'params'}->[0] }) { - push @args, ($_, $paramhash->{'params'}->[0]->{$_}); - } - } - push @{ $request->{arg} }, @args; - my $req = genRequest(); - my $responses = sendRequest($req); - return $responses; -} - -sub sitehdl { - my $params = shift; - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # set the command name - $request->{command} = $params->{'cmd'}; - - # push the -t args - push @args, '-t'; - push @args, 'site'; - if (isGET()) { - push @args, 'clustersite'; - } - if (defined($urilayers[2])) { - if (isGET()) { - push @args, ('-i', $urilayers[2]); - } - } - if (isDelete()) { - if (defined($urilayers[2])) { - push @args, "$urilayers[2]="; - } - } - foreach my $k (keys(%$paramhash)) { - push @args, "$k=$paramhash->{$k}" if ($k); - } - push @{ $request->{arg} }, @args; - my $req = genRequest(); - my $responses = sendRequest($req); - - return $responses; -} - - -# get attrs of tables for a noderange -sub tablenodehdl { - my $params = shift; - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # the array elements for @urilayers are: - # 0 - 'table' - # 1 - - # 2 - 'nodes' - # 3 - (optional) - # 4 - (optional) - - # set the command name - my @tables = split(/,/, $urilayers[1]); - - if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLNODES') { - $request->{command} = 'getTablesAllNodeAttribs'; - } else { - $request->{command} = 'getTablesNodesAttribs'; - $request->{noderange} = $urilayers[3]; - } - - # For both getTablesAllNodeAttribs and getTablesNodesAttribs, the rest of the request strucutre looks like this: - # table => [ - # { - # tablename => nodehm, - # attr => [ - # mgmt, - # cons - # ] - # }, - # { - # tablename => ipmi, - # attr => [ - # ALL - # ] - # } - # ] - - # if they specified attrs, sort/group them by table - my $attrlist = $urilayers[4]; - if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes - my @attrs = split(/,/, $attrlist); - my %attrhash; - foreach my $a (@attrs) { - if ($a =~ /\./) { - my ($table, $attr) = split(/\./, $a); - push @{ $attrhash{$table} }, $attr; - } - else { # the attr doesn't have a table qualifier so apply to all tables - foreach my $t (@tables) { push @{ $attrhash{$t} }, $a; } - } - } - - # deal with all of the tables and the attrs for each table - foreach my $tname (@tables) { - my $table = { tablename => $tname }; - if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; } - else { $table->{attr} = 'ALL'; } - push @{ $request->{table} }, $table; - } - - - my $req = genRequest(); - - # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute - # out of the node hash and make it the key - my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 0, KeyAttr => [] }); - - return $responses; -} - -#get bmc ip address source -#check if bmc user or password is correct -sub bmccheckhdl { - - my $params = shift; - - my @args; - my @urilayers = @{ $params->{'layers'} }; - my $bmc_ip; - my $bmc_user; - my $bmc_pw; - - # set the command name - $request->{command} = $params->{'cmd'}; - - # get bmc ip - if (defined($urilayers[2])) - { - $bmc_ip = $urilayers[2]; - } - - # get bmc user and password - if (defined($urilayers[3])) - { - my @keyvals = split(/,/, $urilayers[3]); - foreach my $kv (@keyvals) - { - my ($key, $value) = split(/\s*=\s*/, $kv, 2); - if ($key eq "bmcuser") - { - $bmc_user = $value; - } - elsif ($key eq "bmcpw") - { - $bmc_pw = $value; - } - } - } - - if ($params->{'resourcename'} eq "checkbmcauth") { - if (isGET()) { - - push @args, "-i"; - push @args, $bmc_ip; - if (defined($bmc_user) && $bmc_user ne "none") - { - push @args, "-u"; - push @args, $bmc_user; - - } - push @args, "-p"; - push @args, $bmc_pw; - push @args, "-c"; - } - } - - if ($params->{'resourcename'} eq "getbmcipsource") { - if (isGET()) { - push @args, "-i"; - push @args, $bmc_ip; - if (defined($bmc_user) && $bmc_user ne "none") - { - push @args, "-u"; - push @args, $bmc_user; - } - push @args, "-p"; - push @args, $bmc_pw; - push @args, "--ipsource"; - } - } - - push @{ $request->{arg} }, @args; - my $req = genRequest(); - my $responses = sendRequest($req); - - return $responses; - - -} - - -#get bmc list for bmcdiscover -sub bmclisthdl { - - my $params = shift; - - my @args; - my @urilayers = @{ $params->{'layers'} }; - my $m_value; - my $ip_range; - - # the array elements for @urilayers are: - # 0 - 'bmcdiscover' - # 1 - (optional) - - # set the command name - $request->{command} = $params->{'cmd'}; - - # get method and ip_range - if (defined($urilayers[2])) - { - my @keyvals = split(/,/, $urilayers[2]); - foreach my $kv (@keyvals) - { - my ($key, $value) = split(/\s*=\s*/, $kv, 2); - if ($key eq "method") - { - $m_value = $value; - } - elsif ($key eq "iprange") - { - $ip_range = $value; - } - } - } - - - if ($params->{'resourcename'} eq "bmcdiscover") { - if (isGET()) { - if (defined($m_value)) - { - push @args, "-s"; - push @args, $m_value; - } - push @args, "--range"; - push @args, $ip_range; - } - - } - - push @{ $request->{arg} }, @args; - my $req = genRequest(); - my $responses = sendRequest($req); - - return $responses; - -} - -# get attrs of tables for keys -sub tablerowhdl { - my $params = shift; - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # the array elements for @urilayers are: - # 0 - 'table' - # 1 - - # 2 - 'rows' - # 3 - (optional) - # 4 - (optional) - - # do stuff that is common between getAttribs and getTablesAllRowAttribs - my @tables = split(/,/, $urilayers[1]); - my $attrlist = $urilayers[4]; - if (!defined($attrlist)) { $attrlist = 'ALL'; } # attr=ALL means get all non-blank attributes - my @attrs = split(/,/, $attrlist); - - # get all rows for potentially multiple tables - if (!defined($urilayers[3]) || $urilayers[3] eq 'ALLROWS') { - $request->{command} = 'getTablesAllRowAttribs'; - - # For getTablesAllRowAttribs, the rest of the request strucutre needs to look like this: - # table => [ - # { - # tablename => nodehm, - # attr => [ - # mgmt, - # cons - # ] - # }, - # { - # tablename => ipmi, - # attr => [ - # ALL - # ] - # } - # ] - - # if they specified attrs, sort/group them by table - my %attrhash; - foreach my $a (@attrs) { - if ($a =~ /\./) { - my ($table, $attr) = split(/\./, $a); - push @{ $attrhash{$table} }, $attr; - } - else { # the attr doesn't have a table qualifier so apply to all tables - foreach my $t (@tables) { push @{ $attrhash{$t} }, $a; } - } - } - - # deal with all of the tables and the attrs for each table - foreach my $tname (@tables) { - my $table = { tablename => $tname }; - if (defined($attrhash{$tname})) { $table->{attr} = $attrhash{$tname}; } - else { $table->{attr} = 'ALL'; } - push @{ $request->{table} }, $table; - } - } - - # for 1 table, get just one row based on the keys given - else { - if (scalar(@tables) > 1) { error('currently you can only specify keys for a single table.', $STATUS_BAD_REQUEST); } - $request->{command} = 'getAttribs'; - - # For getAttribs, the rest of the request strucutre needs to look like this: - # { - # table => networks, - # keys => { - # net => 11.35.0.0, - # mask => 255.255.0.0 - # } - # attr => [ - # netname, - # dhcpserver - # ] - # }, - $request->{table} = $tables[0]; - if (defined($urilayers[3])) { - my @keyvals = split(/,/, $urilayers[3]); - foreach my $kv (@keyvals) { - my ($key, $value) = split(/\s*=\s*/, $kv, 2); - $request->{keys}->{$key} = $value; - } - } - foreach my $a (@attrs) { push @{ $request->{attr} }, $a; } - } - - my $req = genRequest(); - - # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute - # out of the node hash and make it the key - my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 0, KeyAttr => [] }); - - return $responses; -} - -# parse the output of all attrs of tables for the GET calls. This is used for both node-oriented tables -# and non-node-oriented tables. -#todo: investigate a converter straight from xml to json -sub tableout { - my $data = shift; - my $json = {}; - - # For the table get calls, we turned off ForceArray and KeyAttr for XMLin(), so the output is a little - # different than usual. Each element is a hash with key "table" that is either a hash or array of hashes. - # Each element of that is a hash with 2 keys called "tablename" and "node". The latter has either: an array of node hashes, - # or (if there is only 1 node returned) the node hash directly. - # We are producing json that is a hash of table name keys that each have an array of node objects. - foreach my $d (@$data) { - my $table = $d->{table}; - if (!defined($table)) { # special case for the getAttribs cmd - $json->{ $request->{table} }->[0] = $d; - last; - } - - #debug(Dumper($d)); debug (Dumper($jsonnode)); - if (ref($table) eq 'HASH') { $table = [$table]; } # if a single table, make it a 1 element array of tables - foreach my $t (@$table) { - my $jsonnodes = []; # start an array of node objects for this table - my $tabname = $t->{tablename}; - if (!defined($tabname)) { $tabname = 'unknown' . $::i++; } #todo: have lissa fix this bug - $json->{$tabname} = $jsonnodes; # add it into the top level hash - my $node = $t->{node}; - if (!defined($node)) { $node = $t->{row}; } - - #debug(Dumper($d)); debug (Dumper($jsonnode)); - if (ref($node) eq 'HASH') { $node = [$node]; } # if a single node, make it a 1 element array of nodes - foreach my $n (@$node) { push @$jsonnodes, $n; } - } - } - addPageContent($JSON->encode($json)); -} - -# set attrs of nodes in tables -sub tablenodeputhdl { - my $params = shift; - - # from the %URIdef: - # desc => "[URI:/tables/nodes/{noderange}] - Change the table attibutes for the {noderange}.", - # usage => "|An array of table objects. Each table object contains the table name and an object of attribute values. DataBody: {table1:{attr1:v1,att2:v2,...}}.|$usagemsg{non_getreturn}|", - # example => '|Change the nodehm.mgmt and noderes.netboot attributes for nodes node1-node5.|PUT|/tables/nodes/node1-node5 {"nodehm":{"mgmt":"ipmi"},"noderes":{"netboot":"xnba"}}||', - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # the array elements for @urilayers are: - # 0 - 'table' - # 1 - - # 2 - 'nodes' - # 3 - - - # set the command name - $request->{command} = 'setNodesAttribs'; - $request->{noderange} = $urilayers[3]; - - # For setNodesAttribs, the rest of the request strucutre looks like this: - # arg => { - # table => [ - # { - # name => nodehm, - # attr => { - # mgmt => ipmi - # } - # }, - # { - # name => noderes, - # attr => { - # netboot => xnba - # } - # } - # ] - # } - - # Get table list in the URI - my @uritbs = split(/,/, $urilayers[1]); - - # Go thru the list of tables (which are the top level keys in paramhash) - my $tables = []; - $request->{arg}->{table} = $tables; - foreach my $k (keys(%$paramhash)) { - my $intable = $k; - - # Check the validity of tables - if (!grep(/^$intable$/, @uritbs)) { - error("The table $intable is NOT in the URI.", $STATUS_BAD_REQUEST); - } - my $attrhash = $paramhash->{$k}; - my $outtable = { name => $intable, attr => $attrhash }; - push @$tables, $outtable; - } - - my $req = genRequest(); - - # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute - # out of the node hash and make it the key - my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 1, KeyAttr => [] }); - - return $responses; -} - -# set attrs of a row in a non-node table -sub tablerowputhdl { - my $params = shift; - - # from %URIdef: - # desc => "[URI:/tables/{table}/rows/{keys}] - Change the non-node table attibutes for the row that matches the {keys}.", - # usage => "|A hash of attribute names and values. DataBody: {attr1:v1,att2:v2,...}.|$usagemsg{non_getreturn}|", - # example => '|Creat a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet {"net":"10.0.1.0","mask":"255.255.255.0","gateway":"10.0.1.254","ifname":"eth1"}||', - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # the array elements for @urilayers are: - # 0 - 'table' - # 1 - - # 2 - 'rows' - # 3 - - - # set the command name - $request->{command} = 'setAttribs'; - - # For setAttribs, the rest of the xml request strucutre looks like this: - # routes
                                  - # - # foo - # - # - # 10.0.1.0 - # This is a test - # - - # set the table name and keys - $request->{table} = $urilayers[1]; - my @keyvals = split(/,/, $urilayers[3]); - foreach my $kv (@keyvals) { - my ($key, $value) = split(/\s*=\s*/, $kv, 2); - $request->{keys}->{$key} = $value; - } - - # the attribute/value hash is already in paramhash - $request->{attr} = $paramhash; - - my $req = genRequest(); - - # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute - # out of the node hash and make it the key - my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 1, KeyAttr => [] }); - - return $responses; -} - -# delete rows in a non-node table -sub tablerowdelhdl { - my $params = shift; - - # from %URIdef: - # desc => "[URI:/tables/{table}/rows/{attrvals}] - Delete rows from a non-node table that have the attribute values specified in {attrvals}.", - # usage => "||$usagemsg{non_getreturn}|", - # example => '|Delete a route row in the routes table.|PUT|/tables/routes/rows/routename=privnet||', - - my @args; - my @urilayers = @{ $params->{'layers'} }; - - # the array elements for @urilayers are: - # 0 - 'table' - # 1 - - # 2 - 'rows' - # 3 - - - # set the command name - $request->{command} = 'delEntries'; - - # For delEntries, the rest of the xml request strucutre looks like this: - # - # nodelist - # - # compute1,lissa - # down - # - #
                                  - - # set the table name and attr/vals - my $table = {}; # will hold the name and attr/vals - $request->{table}->[0] = $table; #todo: the xcat delEntries cmd supports multiple tables in 1 request. We could support this if the attr names were table.attr - $table->{name} = $urilayers[1]; - my @attrvals = split(/,/, $urilayers[3]); - foreach my $av (@attrvals) { - my ($attr, $value) = split(/\s*=\s*/, $av, 2); - $table->{attr}->{$attr} = $value; - } - - my $req = genRequest(); - - # disabling the KeyAttr option is important in this case, so xmlin doesn't pull the name attribute - # out of the node hash and make it the key - my $responses = sendRequest($req, { SuppressEmpty => undef, ForceArray => 1, KeyAttr => [] }); - - return $responses; -} - - -# display the resource list when run 'xcatws.cgi -d' -sub displayUsage { - foreach my $group (keys %URIdef) { - print "Resource Group: $group\n"; - foreach my $res (keys %{ $URIdef{$group} }) { - print " Resource: $res\n"; - print " $URIdef{$group}->{$res}->{desc}\n"; - if (defined($URIdef{$group}->{$res}->{GET})) { - print " GET: $URIdef{$group}->{$res}->{GET}->{desc}\n"; - } - if (defined($URIdef{$group}->{$res}->{PUT})) { - print " PUT: $URIdef{$group}->{$res}->{PUT}->{desc}\n"; - } - if (defined($URIdef{$group}->{$res}->{POST})) { - print " POST: $URIdef{$group}->{$res}->{POST}->{desc}\n"; - } - if (defined($URIdef{$group}->{$res}->{DELETE})) { - print " DELETE: $URIdef{$group}->{$res}->{DELETE}->{desc}\n"; - } - } - } -} - - -# This handles and removes serverdone and error tags in the perl data structure that is from the xml that xcatd returned -#bmp: is there a way to avoid make a copy of the whole response? For big output that could be time consuming. -# For the error tag, you don't have to bother copying the response, because you are going to exit anyway. -# Maybe this function could just verify there is a serverdone and handle any error, and then -# let each specific output handler ignore the serverdone tag? - -# Filter out the error message -# If has 'error' message in the output data, push them all to one list -# If has 'errorcode' in the output data, set it to be the errorcode of response. Otherwise, the errorcode to '1' -# When get the 'serverdone' identifer -# If 'errorcode' has been set, return the error message and error code like {error:[msg1,msg2...], errorcode:num} -# Otherwise, pass the output to the outputhandler for the specific resource - -sub filterData { - my $data = shift; - - #debugandexit(Dumper($data)); - - my $outputdata; - my $outputerror; - my @errmsgindata; # put the out->{data} for error message output - - #trim the serverdone message off - foreach (@{$data}) { - if (defined($_->{error})) { - if (ref($_->{error}) eq 'ARRAY') { - foreach my $msg (@{ $_->{error} }) { - if ($msg =~ /(Permission denied|Authentication failure)/) { - - # return 401 Unauthorized - error("Authentication failure", $STATUS_UNAUTH); - } else { - push @{ $outputerror->{error} }, $msg; - } - } - } else { - push @{ $outputerror->{error} }, $_->{error}; - } - - if (defined($_->{errorcode})) { - if (ref($_->{errorcode}) eq 'ARRAY') { - $outputerror->{errorcode} = $_->{errorcode}->[0]; - } else { - $outputerror->{errorcode} = $_->{errorcode}; - } - } else { - - # set the default errorcode to '1' - $outputerror->{errorcode} = '1'; - } - } elsif (defined($_->{errorcode}) && $_->{errorcode}->[0] ne "0") { # defined errorcode, but not define the error msg - $outputerror->{errorcode} = $_->{errorcode}->[0]; - if (defined($_->{data}) && ref($_->{data}->[0]) ne "HASH") { - - # to get the message in data for the case that errorcode is set but no 'error' attr - push @errmsgindata, $_->{data}->[0]; - } - if (@errmsgindata) { - push @{ $outputerror->{error} }, @errmsgindata; - } else { - push @{ $outputerror->{error} }, "Failed with unknown reason."; - } - } - - # handle the output like - # - # node1 - # Unable to identify plugin for this command, check relevant tables: nodehm.power,mgt;nodehm.mgt - # 1 - # - if (defined($_->{node}) && defined($_->{node}->[0]->{error})) { - if (defined($_->{node}->[0]->{name})) { - push @{ $outputerror->{error} }, "$_->{node}->[0]->{name}->[0]: " . $_->{node}->[0]->{error}->[0]; - } - if (defined($_->{node}->[0]->{errorcode})) { - $outputerror->{errorcode} = $_->{node}->[0]->{errorcode}->[0]; - } else { - - # set the default errorcode to '1' - $outputerror->{errorcode} = '1'; - } - } - - - if (exists($_->{serverdone})) { - if (defined($outputerror->{error}) || defined($outputerror->{error})) { - addPageContent($JSON->encode($outputerror)); - - #return the default http error code to be 403 forbidden - sendResponseMsg($STATUS_FORBIDDEN); - - #} else { - #otherwise, ignore the 'servicedone' data - # next; - } else { - delete($_->{serverdone}); - if (scalar(keys %{$_}) > 0) { - push @{$outputdata}, $_; - } - } - } else { - if (defined($_->{data}) && ref($_->{data}->[0]) ne "HASH") { - - # to get the message in data for the case that errorcode is set but no 'error' attr - push @errmsgindata, $_->{data}->[0]; - } - push @{$outputdata}, $_; - } - } - - return $outputdata; -} - -# Structure the response perl data structure into well-formed json. Since the structure of the -# xml output that comes from xcatd is inconsistent and not very structured, we have a lot of work to do. -sub wrapJson { - - # this is an array of responses from xcatd. Often all the output comes back in 1 response, but not always. - my $data = shift; - - addPageContent($JSON->encode($data)); - return; - - - # put, delete, and patch usually just give a short msg, if anything - if (isPut() || isDelete() || isPatch()) { - addPageContent($JSON->encode($data)); - return; - } -} - -# Append content to the global var holding the output to go back to the rest client -# 1st param - The output message -# 2nd param - A flag to specify the format of 1st param: 1 - json formatted standard xcat output data sub addPageContent { my $newcontent = shift; - my $userdata = shift; - - if ($userdata && $XCOLL) { - my $group; - my $hash = $JSON->decode($newcontent); - if (ref($hash) eq "HASH") { - foreach my $node (keys %{$hash}) { - if (ref($hash->{$node}) eq "HASH") { - my $value; - foreach (sort (keys %{ $hash->{$node} })) { - $value .= "$_$hash->{$node}->{$_}"; - } - push @{ $group->{$value}->{node} }, $node; - $group->{$value}->{orig} = $hash->{$node}; - } elsif (ref($hash->{$node}) eq "ARRAY") { - my $value; - foreach (sort (@{ $hash->{$node} })) { - $value .= "$_"; - } - push @{ $group->{$value}->{node} }, $node; - $group->{$value}->{orig} = $hash->{$node}; - } - } - } - my $groupout; - foreach my $value (keys %{$group}) { - if (defined $group->{$value}->{node}) { - my $nodes = join(',', @{ $group->{$value}->{node} }); - if (defined($group->{$value}->{orig})) { - $groupout->{$nodes} = $group->{$value}->{orig}; - } - } - } - $newcontent = $JSON->encode($groupout) if ($groupout); - } - $pageContent .= $newcontent; } -# send the response to client side, then exit -# with http there is only one return for each request, so all content should be in pageContent global variable when you call this -# create the response header by status code and format +#send the response to client side +#the http only return once in each request, so all content shoudl save in a global variable, +#create the response header by status sub sendResponseMsg { my $code = shift; my $tempFormat = ''; @@ -3164,44 +65,2334 @@ sub sendResponseMsg { elsif ('xml' eq $format) { $tempFormat = 'text/xml'; } - elsif ('stream' eq $format) { - $tempFormat = 'application/octet-stream'; - } else { $tempFormat = 'text/html'; } - - if ($header_info{attachment}) { - print $q->header(-status => $code, - -type => $tempFormat, - -attachment => $header_info{attachment}, - -Content_length => length($pageContent)); - } else { - print $q->header(-status => $code, -type => $tempFormat); - if ($pageContent) { $pageContent .= "\n"; } # if there is any content, append a newline - } + print $q->header(-status => $code, -type => $tempFormat); print $pageContent; exit(0); } -# Convert xcat request to xml for sending to xcatd -sub genRequest { - my $xml = XML::Simple::XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []); +sub unsupportedRequestType { + addPageContent("request method '$requestType' is not supported on resource '$resource'"); + sendResponseMsg($STATUS_NOT_ALLOWED); } -# Send the request to xcatd and read the response. The request passed in has already been converted to xml. -# The response returned to the caller of this function has already been converted from xml to perl structure. +use XML::Simple; +$XML::Simple::PREFERRED_PARSER = 'XML::Parser'; + +sub genRequest { + if ($DEBUGGING) { + addPageContent($q->p("request " . Dumper($request))); + } + my $xml = XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []); +} + +#data formatters. To add one simple copy the format of an existing one +# and add it to this hash +my %formatters = ( + 'html' => \&wrapHtml, + 'json' => \&wrapJson, + 'xml' => \&wrapXml,); + +fetchParameter($queryString); + +if ($queryhash{'format'}) { + $format = $queryhash{'format'}->[0]; + if (!exists $formatters{$format}) { + addPageContent("The format '$format' is not valid"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if ($format eq 'json') { + # require JSON dynamically and let them know if it is not installed + my $jsoninstalled = eval { require JSON; }; + unless ($jsoninstalled) { + addPageContent('{"data":"JSON perl module missing. Install perl-JSON before using the xCAT REST web services API."}'); + sendResponseMsg($STATUS_SERVICE_UNAVAILABLE); + } + } +} + +my $XCAT_PATH = '/opt/xcat/bin'; + +#resource handlers +my %resources = ( + groups => \&groupsHandler, + images => \&imagesHandler, + logs => \&logsHandler, + monitors => \&monitorsHandler, + networks => \&networksHandler, + nodes => \&nodesHandler, + notifications => \¬ificationsHandler, + policies => \&policiesHandler, + site => \&siteHandler, + tables => \&tablesHandler, + accounts => \&accountsHandler, + objects => \&objectsHandler, + vms => \&vmsHandler, + debug => \&debugHandler, + hypervisor => \&hypervisorHandler, + version => \&versionHandler); + +#if no resource was specified +if ($pathInfo =~ /^\/$/ || $pathInfo =~ /^$/) { + addPageContent($q->p("This is the root page for the xCAT Rest Web Service. Available resources are:")); + foreach (sort keys %resources) { + addPageContent($q->p($_)); + } + sendResponseMsg($STATUS_OK); +} + +sub doesResourceExist { + my $res = shift; + return exists $resources{$res}; +} + +if ($DEBUGGING) { + if (defined $q->param('PUTDATA')) { + addPageContent("put data " . $q->p($q->param('PUTDATA') . "\n")); + } elsif (isPut()) { + my $entries = JSON::decode_json($q->param('PUTDATA')); + if (scalar(@$entries) >= 1) { + addPageContent("put data \n"); + foreach (@$entries) { + addPageContent("$_\n"); + } + } + } + + if (defined $q->param('POSTDATA')) { + addPageContent("post data " . $q->p($q->param('POSTDATA') . "\n")); + } elsif (isPost()) { + my $entries = JSON::decode_json($q->param('POSTDATA')); + if (scalar(@$entries) >= 1) { + addPageContent("post data \n"); + foreach (@$entries) { + addPageContent("$_\n"); + } + } + } + + addPageContent($q->p("Parameters ")); + my @params = $q->param; + foreach (@params) { + addPageContent("$_ = " . join(',', $q->param($_)) . "\n"); + } + addPageContent($q->p("Query String $queryString" . "\n")); + addPageContent($q->p("Query parameters from the Query String" . Dumper(\%queryhash) . "\n")); + addPageContent($q->p("HTTP Method $requestType" . "\n")); + addPageContent($q->p("URI $url" . "\n")); + addPageContent($q->p("path " . Dumper(@path) . "\n")); +} + +#when use put and post, can not fetch the url-parameter, so add this sub to support all kinks of method +sub fetchParameter { + my $parstr = shift; + unless ($parstr) { + return; + } + + my @pairs = split(/&/, $parstr); + foreach my $pair (@pairs) { + my ($key, $value) = split(/=/, $pair, 2); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg; + push @{$queryhash{$key}}, $value; + } +} + +#extract the put data or post data into perl hash, easy for retrieve +sub extractData { + my $temphash = shift; + my $parArray = shift; + my $key; + my $value; + my $position; + + #traversal all element in the array + foreach (@$parArray) { + $position = index($_, '='); + if ($position < 0) { + $key = $_; + $value = 1; + } + else { + $key = substr $_, 0, $position; + $value = substr $_, $position + 1; + } + $temphash->{$key} = $value; + + if ($DEBUGGING) { + addPageContent($q->p("The parameter extract from put/post data:
                                  " . Dumper($temphash))); + } + } +} + +my $userName=http('userName'); +my $password=http('password'); + +sub handleRequest { + if (defined $queryhash{'userName'}) { + $userName = $queryhash{'userName'}->[0]; + } + if (defined $queryhash{'password'}) { + $password = $queryhash{'password'}->[0]; + } + if ($userName && $password) { + $request->{becomeuser}->[0]->{username}->[0] = $userName; + $request->{becomeuser}->[0]->{password}->[0] = $password; + } + my @data = $resources{$resource}->(); + wrapData(\@data); +} + +my @groupFields = ('groupname', 'grouptype', 'members', 'wherevals', 'comments', 'disable'); + +#get is done +#post and delete are done but not tested +#groupfiles4dsh is done but not tested +sub groupsHandler { + my @responses; + my @args; + my $groupName; + + #is the group name in the URI? + if (defined $path[1]) { + $groupName = $path[1]; + } + + #in the query string? + else { + $groupName = $q->param('groupName'); + } + + if (isGet()) { + if (defined $groupName) { + $request->{command} = 'gettab'; + push @args, "groupname=$groupName"; + if (defined $q->param('field')) { + foreach ($q->param('field')) { + push @args, "nodegroup.$_"; + } + } + else { + foreach (@groupFields) { + push @args, "nodegroup.$_"; + } + } + } + else { + $request->{command} = 'tabdump'; + push @args, 'nodegroup'; + } + } + + #does it make sense to even have this? + elsif (isPost()) { + my $nodeRange = $q->param('nodeRange'); + if ((defined $groupName) && (defined $nodeRange)) { + $request->{command} = 'mkdef'; + push @args, '-t'; + push @args, 'group'; + push @args, '-o'; + push @args, $groupName; + push @args, "members=$nodeRange"; + } + else { + addPageContent("A node range and group name must be specified for creating a group"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + elsif (isPut()) { + + #handle groupfiles4dsh -p /tmp/nodegroupfiles + if ($q->param('command') eq "4dsh") { + if ($q->param('path')) { + $request->{command} = 'groupfiles4dsh'; + push @args, "p=$q->param('path')"; + } + else { + addPageContent("The path must be specified for creating directories for dsh"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + if (defined $groupName && defined $q->param('fields')) { + $request->{command} = 'nodegrpch'; + push @args, $groupName; + push @args, $q->param('field'); + } + else { + addPageContent("The group and fields must be specified to update groups"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + } + elsif (isDelete()) { + if (defined $groupName) { + $request->{command} = 'rmdef'; + push @args, '-t'; + push @args, 'group'; + push @args, '-o'; + push @args, $groupName; + } + else { + addPageContent("The group must be specified to delete a group"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + + return @responses; +} + +my @imageFields = ( + 'imagename', 'profile', 'imagetype', 'provmethod', 'osname', 'osvers', + 'osdistro', 'osarch', 'synclists', 'comments', 'disable'); + +#get is done, nothing else +sub imagesHandler { + my @responses; + my @args; + my $image; + my $subResource; + + if (defined($path[1])) { + $image = $path[1]; + } + + if (isGet()) { + $request->{command} = 'lsdef'; + push @args, '-t', 'osimage'; + if (defined $image) { + push @args, '-o', $image; + } + if (defined($q->param('field'))) { + push @args, '-i'; + push @args, join(',', $q->param('field')); + } + if (defined($q->param('criteria'))) { + foreach ($q->param('criteria')) { + push @args, '-w', "$_"; + } + } + } + elsif (isPost()) { + my $operationname = $image; + my $entries; + my %entryhash; + + #check the post data + unless (defined($q->param('POSTDATA'))) { + addPageContent("Invalid Parameters"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + $entries = JSON::decode_json($q->param('POSTDATA')); + if (scalar(@$entries) < 1) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + extractData(\%entryhash, $entries); + + #for image capture + if ($operationname eq 'capture') { + $request->{command} = 'imgcapture'; + if (defined($entryhash{'nodename'})) { + $request->{noderange} = $entryhash{'nodename'}; + } + else { + addPageContent('No node range.'); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if (defined($entryhash{'profile'})) { + push @args, '-p'; + push @args, $entryhash{'profile'}; + } + if (defined($entryhash{'osimage'})) { + push @args, '-o'; + push @args, $entryhash{'osimage'}; + } + if (defined($entryhash{'bootinterface'})) { + push @args, '-i'; + push @args, $entryhash{'bootinterface'}; + } + if (defined($entryhash{'netdriver'})) { + push @args, '-n'; + push @args, $entryhash{'netdriver'}; + } + if (defined($entryhash{'device'})) { + push @args, '-d'; + push @args, $entryhash{'device'}; + } + if (defined($entryhash{'compress'})) { + push @args, '-c'; + push @args, $entryhash{'compress'}; + } + } + elsif ($operationname eq 'export') { + $request->{command} = 'imgexport'; + if (defined($entryhash{'osimage'})) { + push @args, $entryhash{'osimage'}; + } + else { + addPageContent('No image specified'); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if (defined($entryhash{'destination'})) { + push @args, $entryhash{'destination'}; + } + if (defined($entryhash{'postscripts'})) { + push @args, '-p'; + push @args, $entryhash{'postscripts'}; + } + if (defined($entryhash{'extra'})) { + push @args, '-e'; + push @args, $entryhash{'extra'}; + } + if (defined($entryhash{'remotehost'})) { + push @args, '-R'; + push @args, $entryhash{'remotehost'}; + } + if (defined($entryhash{'verbose'})) { + push @args, '-v'; + } + } + elsif ($operationname eq 'import') { + $request->{command} = 'imgimport'; + if (defined($entryhash{'osimage'})) { + push @args, $entryhash{'osimage'}; + } + else { + addPageContent('No image specified'); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if (defined($entryhash{'profile'})) { + push @args, '-f'; + push @args, $entryhash{'profile'}; + } + if (defined($entryhash{'remotehost'})) { + push @args, '-R'; + push @args, $entryhash{'remotehost'}; + } + if (defined($entryhash{'postscripts'})) { + push @args, '-p'; + push @args, $entryhash{'postscripts'}; + } + if (defined($entryhash{'nozip'})) { + push @args, '-n'; + } + + if (defined($entryhash{'verbose'})) { + push @args, '-v'; + } + } + } + elsif (isPut()) { + + #check the operation type + unless (defined $path[2]) { + addPageContent("The subResource $subResource does not exist"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + $subResource = $path[2]; + + #check the image name + unless (defined $image) { + addPageContent("The image name is required to clean an os image"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if ($subResource eq 'check') { + $request->{command} = 'chkosimage'; + if (defined($q->param('PUTDATA'))) { + push @args, '-c'; + } + push @args, $image; + } + else { + addPageContent("The subResource $subResource does not exist"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + elsif (isDelete()) { + if (defined $image) { + $request->{command} = 'rmimage'; + if (defined $q->param('verbose')) { + push @args, '-v'; + } + push @args, $image; + } + elsif (defined $q->param('os') && defined $q->param('arch') && defined $q->param('profile')) { + push @args, '-o'; + push @args, $q->param('os'); + push @args, '-a'; + push @args, $q->param('arch'); + push @args, '-p'; + push @args, $q->param('profile'); + } + else { + addPageContent( + "Either the image name or the os, architecture and profile must be specified to remove an image"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + + return @responses; +} + +#complete +sub logsHandler { + my @responses; + my @args; + my $logType; + + if (defined $path[1]) { + $logType = $path[1]; + } + + #in the query string? + else { + $logType = $q->param('logType'); + } + my $nodeRange = $q->param('nodeRange'); + + #no real output unless the log type is defined + if (!defined $logType) { + addPageContent("Current logs available are auditlog, eventlog, and diagnostics"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if (isGet()) { + if ($logType eq "reventLog") { + if (defined $nodeRange) { + $request->{command} = 'reventlog'; + push @args, $nodeRange; + if (defined $q->param('count')) { + push @args, $q->param('count'); + } + } + else { + addPageContent("nodeRange must be specified to GET remote event logs"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + elsif ($logType eq "diagnostics") { + addPageContent(uc($requestType) . " remote diagnostic logs is not supported"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + else { + $request->{command} = 'tabdump'; + push @args, $logType; + } + } + + #this clears the log + elsif (isPut()) { + if ($logType eq "reventlog") { + if (defined $nodeRange) { + $request->{command} = 'reventlog'; + push @args, $nodeRange; + push @args, 'clear'; + } + else { + addPageContent("nodeRange must be specified to clean remote event logs"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + elsif ($logType eq "diagnostics") { + addPageContent(uc($requestType) . " remote diagnostic logs is not supported"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + else { + + #should it return the removed entries? + if (defined $q->param('showRemoved')) { + push @args, '-V'; + } + if (defined $q->param('count') || defined $q->param('percent') || defined $q->param('lastRecord')) { + + #remove some of the entries + $request->{command} = 'tabprune'; + + #remove a certain number of records + if (defined $q->param('count')) { + push @args, ('-n', $q->param('count')); + } + + #remove a percentage of the records + if (defined $q->param('percent')) { + push @args, ('-p', $q->param('percent')); + } + + #remove all records before this record + if (defined $q->param('lastRecord')) { + push @args, ('-i', $q->param('lastRecord')); + } + } + else { + $request->{command} = 'tabprune'; + + #-a removes all + push @args, '-a'; + } + } + } + # Currently, only diagnostic logs can be created + elsif (isPost()) { + if ($logType eq "diagnostics") { + + # Potential base bug on the reventlog and auditlog paths: + # $q->param('nodeRange') != $queryhash{'nodeRange'} + # The base code uses the first, which is undef even when a URL + # query parameter named nodeRange was passed by the caller (e.g. is + # found in the nova-compute.log traces). + # Re-assigning nodeRange on this new path since it does return + # a value. + + $nodeRange = $queryhash{'nodeRange'}; + if (defined $nodeRange) { + $request->{command} = 'diagnostics'; + $request->{noderange} = $nodeRange; + + my $parameter; + # Parse the optional upstream request ID, e.g. an OpenStack request UUID + $parameter = 'requestid'; + if (defined $queryhash{$parameter}) { + push @args, '--'.$parameter; + push @args, $queryhash{$parameter}->[0]; + } + + # Parse the optional upstream object ID, e.g. an OpenStack nova instance UUID + $parameter = 'objectid'; + if (defined $queryhash{$parameter}) { + push @args, '--'.$parameter; + push @args, $queryhash{$parameter}->[0]; + } + + unless ($q->param('POSTDATA')) { + addPageContent("A request body containing parameters is required"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + # Collect all parameters from the postdata + my %entryhash; + my $entries = JSON::decode_json($q->param('POSTDATA')); + if (scalar(@$entries) < 1) { + addPageContent("No request parameters were supplied in the message body."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + extractData(\%entryhash, $entries); + # TODO: add parameter parsing back in to pass through all body parameters. + # How to handle duplicate property names? Perhaps prefix them with upstream_ , and pass the prefix too ;-) + + # Parse the optional body parameters from the caller (NOT URL query parameters) + # TODO: this is early code that hard-codes a single key passed by the + # z/VM OpenStack nova plugin. It will be replaced later with more + # general code that behaves similarly. + $parameter = 'reason'; + if (defined $entryhash{$parameter}) { + push @args, '--upstream-'.$parameter; + push @args, $entryhash{$parameter}; + } + + } + else { + addPageContent("nodeRange must be specified to collect diagnostics"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + addPageContent("POST is only valid for logType(s): diagnostics. It is not valid with the supplied logType: $logType"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + + return @responses; +} + +#complete +sub monitorsHandler { + my @responses; + my @args; + my $monitor; + + if (defined $path[1]) { + $monitor = $path[1]; + } + + #in the query string? + elsif (defined $q->param('monitor')) { + push @args, $q->param('monitor'); + } + if (defined $monitor) { + push @args, $monitor; + } + + if (isGet()) { + $request->{command} = 'monls'; + } + elsif (isPost()) { + $request->{command} = 'monadd'; + if ($q->param('nodeStatMon')) { + push @args, '-n'; + } + + #get the plug-in specific settings array + foreach ($q->param('pluginSetting')) { + push @args, '-s'; + push @args, $_; + } + } + elsif (isDelete()) { + $request->{command} = 'monrm'; + } + elsif (isPut() || isPatch()) { + my $action = $q->param('action'); + if ($action eq "start") { + $request->{command} = 'monstart'; + } + elsif ($action eq "stop") { + $request->{command} = 'monstop'; + } + elsif ($action eq "config") { + $request->{command} = 'moncfg'; + } + elsif ($action eq "deconfig") { + $request->{command} = 'mondeconfig'; + } + else { + unsupportedRequestType(); + } + if (!defined $q->param('nodeRange')) { + + #error + } + else { + push @args, $q->param('nodeRange'); + } + if (defined $q->param('remote')) { + push @args, '-r'; + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + + return @responses; +} + +sub networksHandler { + my @responses; + my @args; + my $netname = ''; + + if (isGet()) { + $request->{command} = 'lsdef'; + push @{$request->{arg}}, '-t', 'network'; + if (defined($path[1])) { + push @{$request->{arg}}, '-o', $path[1]; + } + my @temparray = $q->param('field'); + + #add the field name to get + if (scalar(@temparray) > 0) { + push @{$request->{arg}}, '-i'; + push @{$request->{arg}}, join(',', @temparray),; + } + } + elsif (isPut() || isPost()) { + my $entries; + my $iscommand = 0; + if (isPut()) { + $request->{command} = 'chdef'; + if (defined($path[1])) { + if ($path[1] eq "makehosts" || $path[1] eq "makedns") { + # Issue makehost/makedns directly + $request->{command} = $path[1]; + $iscommand = 1; + } + } + } + else { + $request->{command} = 'mkdef'; + } + + if (!$iscommand) { + if (defined $path[1]) { + $netname = $path[1]; + } + + if ($netname eq '') { + addPageContent('A network name must be specified.'); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + push @{$request->{arg}}, '-t', 'network', '-o', $netname; + + if (defined($q->param('PUTDATA'))) { + $entries = JSON::decode_json($q->param('PUTDATA')); + } + elsif (defined($q->param('POSTDATA'))) { + $entries = JSON::decode_json($q->param('POSTDATA')); + } + else { + addPageContent("No Field and Value map was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if (scalar($entries) < 1) { + addPageContent("No Field and Value map was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + foreach (@$entries) { + push @{$request->{arg}}, $_; + } + } + } + elsif (isDelete()) { + $request->{command} = 'rmdef'; + + if (defined $path[1]) { + $netname = $path[1]; + } + if ($netname eq '') { + addPageContent('A network name must be specified.'); + sendResponseMsg($STATUS_BAD_REQUEST); + } + push @{$request->{arg}}, '-t', 'network', '-o', $netname; + } + else { + unsupportedRequestType(); + exit(0); + } + @responses = sendRequest(genRequest()); + + return @responses; +} + +sub nodesHandler { + my @responses; + my @args; + my $noderange; + my @envs; + + if (defined $path[1]) { + $noderange = $path[1]; + } + + if (isGet()) { + my $subResource; + if (defined $path[2]) { + $subResource = $path[2]; + unless (defined($noderange)) { + addPageContent("Invalid nodes and/or groups in noderange"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + $request->{noderange} = $noderange; + + #use the corresponding command by the subresource name + if ($subResource eq "power") { + $request->{command} = 'rpower'; + + #no fields will default to 'stat' + if (defined $q->param('field')) { + push @args, $q->param('field'); + } + else { + push @args, 'stat'; + } + } + elsif ($subResource eq "energy") { + $request->{command} = 'renergy'; + + #no fields will default to 'all' + if (defined $q->param('field')) { + push @args, $q->param('field'); + } + else { + push @args, 'all'; + } + } + elsif ($subResource eq "status") { + $request->{command} = 'nodestat'; + } + elsif ($subResource eq "inventory") { + $request->{command} = 'rinv'; + if (defined $q->param('field')) { + push @args, $q->param('field'); + } + else { + push @args, 'all'; + } + } + elsif ($subResource eq "vitals") { + $request->{command} = 'rvitals'; + if (defined $q->param('field')) { + push @args, $q->param('field'); + } + else { + push @args, 'all'; + } + } + elsif ($subResource eq "scan") { + $request->{command} = 'rscan'; + if (defined $q->param('field')) { + push @args, $q->param('field'); + } + } + else { + addPageContent("Unspported operation on nodes object."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + $request->{command} = 'lsdef'; + push @args, "-t", "node"; + + #add the nodegroup into args + if (defined($noderange)) { + push @args, "-o", $noderange; + } + + #maybe it's specified in the parameters + my @temparray = $q->param('field'); + if (scalar(@temparray) > 0) { + push @args, "-i"; + push @args, join(',', @temparray); + } + } + } + elsif (isPut()) { + my $subResource; + my @entries; + my $entrydata; + + unless (defined($noderange)) { + addPageContent("Invalid nodes and/or groups in noderange"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + $request->{noderange} = $noderange; + + unless ($q->param('PUTDATA')) { + #temporary allowance for the put data to be contained in the queryString + unless ($queryhash{'putData'}) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + else { + foreach my $put (@{$queryhash{'putData'}}) { + my ($key, $value) = split(/=/, $put, 2); + if ($key eq 'field' && $value) { + push @entries, $value; + } + } + } + } + else { + @entries = JSON::decode_json($q->param('PUTDATA')); + if (scalar(@entries) < 1) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + + if (defined $path[2]) { + $subResource = $path[2]; + + if (($subResource ne "dsh") && ($subResource ne "dcp")) { + # For any function other than "dsh" or "dcp", + # move all operands to the argument list. + foreach (@entries) { + if (ref($_) eq 'ARRAY') { + foreach (@$_) { + push @args, $_; + } + } else { + push @args, $_; + } + } + } + if ($subResource eq "power") { + $request->{command} = "rpower"; + my %elements; + extractData(\%elements, @entries); + + unless (scalar(%elements)) { + addPageContent("No power operands were supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + elsif ($subResource eq "energy") { + $request->{command} = "renergy"; + } + elsif ($subResource eq "bootstat" or $subResource eq "bootstate") { + $request->{command} = "nodeset"; + } + elsif ($subResource eq "bootseq") { + $request->{command} = "rbootseq"; + } + elsif ($subResource eq "setboot") { + $request->{command} = "rsetboot"; + } + elsif ($subResource eq "migrate") { + $request->{command} = "rmigrate"; + } + elsif ($subResource eq "execcmdonvm") { + $request->{command} = "execcmdonvm"; + } + elsif ($subResource eq "dsh") { + $request->{command} = "xdsh"; + my %elements; + extractData(\%elements, @entries); + if (defined($elements{'devicetype'})) { + push @args, '--devicetype'; + push @args, $elements{'devicetype'}; + } + if (defined($elements{'execute'})) { + push @args, '-e'; + } + if (defined($elements{'environment'})) { + push @args, '-E'; + push @args, $elements{'environment'}; + } + if (defined($elements{'fanout'})) { + push @args, '-f'; + push @args, $elements{'fanout'}; + } + if (defined($elements{'nolocale'})) { + push @args, '-L'; + } + if (defined($elements{'userid'})) { + push @args, '-l'; + push @args, $elements{'userid'}; + } + if (defined($elements{'monitor'})) { + push @args, '-m'; + } + if (defined($elements{'options'})) { + push @args, '-o'; + push @args, $elements{'options'}; + } + if (defined($elements{'showconfig'})) { + push @args, '-q'; + } + if (defined($elements{'silent'})) { + push @args, '-Q'; + } + if (defined($elements{'remoteshell'})) { + push @args, '-r'; + push @args, $elements{'remoteshell'}; + } + if (defined($elements{'syntax'})) { + push @args, '-S'; + push @args, $elements{'syntax'}; + } + if (defined($elements{'timeout'})) { + push @args, '-t'; + push @args, $elements{'timeout'}; + } + if (defined($elements{'envlist'})) { + push @args, '-X'; + push @args, $elements{'envlist'}; + } + if (defined($elements{'sshsetup'})) { + push @args, '-K'; + push @args, $elements{'sshsetup'}; + } + if (defined($elements{'rootimg'})) { + push @args, '-i'; + push @args, $elements{'rootimg'}; + } + if (defined($elements{'command'})) { + push @args, $elements{'command'}; + } + if (defined($elements{'remotepasswd'})) { + push @envs, 'DSH_REMOTE_PASSWORD=' . $elements{'remotepasswd'}; + push @envs, 'DSH_FROM_USERID=root'; + push @envs, 'DSH_TO_USERID=root'; + } + } + elsif ($subResource eq "dcp") { + $request->{command} = "xdcp"; + my %elements; + extractData(\%elements, @entries); + if (defined($elements{'fanout'})) { + push @args, '-f'; + push @args, $elements{'fanout'}; + } + if (defined($elements{'rootimg'})) { + push @args, '-i'; + push @args, $elements{'rootimg'}; + } + if (defined($elements{'options'})) { + push @args, '-o'; + push @args, $elements{'options'}; + } + if (defined($elements{'rsyncfile'})) { + push @args, '-F'; + push @args, $elements{'rsyncfile'}; + } + if (defined($elements{'preserve'})) { + push @args, '-p'; + } + if (defined($elements{'pull'})) { + push @args, '-P'; + } + if (defined($elements{'showconfig'})) { + push @args, '-q'; + } + if (defined($elements{'remotecopy'})) { + push @args, '-r'; + push @args, $elements{'remotecopy'}; + } + if (defined($elements{'recursive'})) { + push @args, '-R'; + } + if (defined($elements{'timeout'})) { + push @args, '-t'; + push @args, $elements{'timeout'}; + } + if (defined($elements{'source'})) { + push @args, $elements{'source'}; + } + if (defined($elements{'target'})) { + push @args, $elements{'target'}; + } + } + } + else { + my %elements; + my $name; + my $val; + + $request->{command} = "tabch"; + push @args, "node=" . $request->{noderange}; + + extractData(\%elements, @entries); + while (($name, $val) = each (%elements)) { + push @args, $name . "=" . $val; + } + } + } + elsif (isPost()) { + $request->{command} = 'mkdef'; + push @args, "-t", "node"; + + unless (defined($noderange)) { + addPageContent("No nodename was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + push @args, "-o", $noderange; + + if ($q->param('POSTDATA')) { + my $entries = JSON::decode_json($q->param('POSTDATA')); + if (scalar($entries) < 1) { + addPageContent("No Field and Value map was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + foreach (@$entries) { + push @args, $_; + } + } + } + elsif (isDelete()) { + + #FYI: the nodeRange for delete has to be specified in the URI + $request->{command} = 'rmdef'; + push @args, "-t", "node"; + unless (defined($noderange)) { + addPageContent("No nodename was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + push @args, "-o", $noderange; + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + if (@envs) { + push @{$request->{env}}, @envs; + } + my $req = genRequest(); + @responses = sendRequest($req); + + return @responses; +} + +my @notificationFields = ('filename', 'tables', 'tableops', 'comments', 'disable'); + +#complete, unless there is some way to alter existing notifications +sub notificationsHandler { + my @responses; + my @args; + + #does not support using the notification fileName in the URI + + if (isGet()) { + if (defined $q->param('fileName')) { + $request->{command} = 'gettab'; + push @args, "filename" . $q->param('fileName'); + + #if they specified the fields, just get those + if (defined $q->param('field')) { + foreach ($q->param('field')) { + push @args, $_; + } + } + + #else show all of the fields + else { + foreach (@notificationFields) { + push @args, "notification.$_"; + } + } + } + else { + $request->{command} = 'tabdump'; + push @args, "notification"; + } + } + elsif (isPost()) { + $request->{command} = 'regnotif'; + if (!defined $q->param('fileName') || !defined $q->param('table') || !defined $q->param('operation')) { + addPageContent("fileName, table and operation must be specified for a POST on /notifications"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + else { + push @args, $q->param('fileName'); + my $tables; + foreach ($q->param('table')) { + $tables .= "$_,"; + } + + #get rid of the extra comma + chop($tables); + push @args, $tables; + push @args, '-o'; + my $operations; + foreach ($q->param('operation')) { + $operations .= "$_,"; + } + + #get rid of the extra comma + chop($operations); + push @args, $q->param('operation'); + } + } + elsif (isDelete()) { + $request->{command} = 'unregnotif'; + if (defined $q->param('fileName')) { + push @args, $q->param('fileName'); + } + else { + addPageContent("fileName must be specified for a DELETE on /notifications"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + addPageContent("request is " . Dumper($request)); + my $req = genRequest(); + @responses = sendRequest($req); + + return @responses; +} + +my @policyFields = + ('priority', 'name', 'host', 'commands', 'noderange', 'parameters', 'time', 'rule', 'comments', 'disable'); + +#complete +sub policiesHandler { + my @responses; + my @args; + my $priority; + + #does it specify the prioirty in the URI? + if (defined $path[1]) { + $priority = $path[1]; + } + + #in the query string? + elsif (defined $q->param('priority')) { + $priority = $q->param('priority'); + } + + if (isGet()) { + if (defined $priority) { + $request->{command} = 'gettab'; + push @args, "priority=$priority"; + my @fields = $q->param('field'); + + #if they specified fields to retrieve + if (@fields) { + push @args, @fields; + } + + #give them everything if nothing is specified + else { + foreach (@policyFields) { + push @args, "policy.$_"; + } + } + } + else { + $request->{command} = 'tabdump'; + push @args, 'policy'; + } + } + elsif (isPost()) { + if (defined $priority) { + $request->{command} = 'tabch'; + push @args, "priority=$priority"; + for ($q->param) { + if ($_ ne /priority/) { + push @args, "policy.$_=" . $q->param($_); + } + } + } + + #some response about the priority being required + else { + addPageContent("The priority must be specified when creating a policy"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + elsif (isDelete()) { + + #just allowing a delete by priority at the moment, could expand this to anything + if (defined $priority) { + $request->{command} = 'tabch'; + push @args, '-d'; + push @args, "priority=$priority"; + push @args, "policy"; + } + } + elsif (isPut() || isPatch()) { + if (defined $priority) { + $request->{command} = 'tabch'; + push @args, "priority=$priority"; + for ($q->param) { + if ($_ ne /priority/) { + push @args, "policy.$_=" . $q->param($_); + } + } + } + + #some response about the priority being required + else { + addPageContent("The priority must be specified when updating a policy"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + addPageContent("request is " . Dumper($request)); + my $req = genRequest(); + @responses = sendRequest($req); + + return @responses; +} + +#complete +sub siteHandler { + my @data; + my @responses; + my @args; + + if (isGet()) { + $request->{command} = 'lsdef'; + push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite'; + my @temparray = $q->param('field'); + + #add the field name to get + if (scalar(@temparray) > 0) { + push @{$request->{arg}}, '-i'; + push @{$request->{arg}}, join(',', @temparray); + } + } + elsif (isPut()) { + $request->{command} = 'chdef'; + push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite'; + unless ($q->param('PUTDATA')) { + #temporary allowance for the put data to be contained in the queryString + unless ($queryhash{'putData'}) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + else { + foreach my $put (@{$queryhash{'putData'}}) { + my ($key, $value) = split(/=/, $put, 2); + if ($key eq 'field' && $value) { + push @{$request->{arg}}, $value; + } + } + } + } else { + if ($q->param('PUTDATA')) { + my $entries = JSON::decode_json($q->param('PUTDATA')); + foreach (@$entries) { + push @{$request->{arg}}, $_; + } + } + else { + addPageContent("No Field and Value map was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + } + else { + unsupportedRequestType(); + } + + my $req = genRequest(); + @responses = sendRequest($req); + return @responses; +} + +my $formatType; + +#provide direct table access +#complete and tested on the site table +#use of the actual DELETE doesn't seem to fit here, since a resource would not be deleted +#using PUT or PATCH instead, though it doesn't feel all that correct either +sub tablesHandler { + my @responses; + my $table; + my @args; + + #is the table name specified in the URI? + if (defined $path[1]) { + $table = $path[1]; + } + + #handle all gets + if (isGet()) { + + #table was specified + if (defined $table) { + if (defined($q->param('col'))) { + $request->{command} = 'gettab'; + push @args, $q->param('col') . '=' . $q->param('value'); + my @temparray = $q->param('attribute'); + foreach (@temparray) { + push @args, $table . '.' . $_; + } + } + else { + $request->{command} = 'tabdump'; + push @args, $table; + if (!defined $q->param('desc')) { + $formatType = 'splitCommas'; + } + } + } + else { + $request->{command} = 'tabdump'; + } + } + elsif (isPut() || isPatch()) { + my $condition = $q->param('condition'); + my @vals; + my $entries; + if (!defined $condition) { + unless ($q->param('PUTDATA')) { + foreach my $put (@{$queryhash{'putData'}}) { + my ($key, $value) = split(/=/, $put, 2); + if ($key eq 'condition' && $value) { + $condition = $value; + } + } + foreach my $put (@{$queryhash{'putData'}}) { + my ($key, $value) = split(/=/, $put, 2); + if ($key eq 'value') { + push(@vals, $value); + } + } + } + else { + $entries = JSON::decode_json($q->param('PUTDATA')); + if (scalar(@$entries) < 1) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + } + + if (!defined $table || !defined $condition) { + if (scalar(@$entries) < 1) { + addPageContent("The table and condition must be specified when adding, changing or deleting an entry"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + $request->{command} = 'tabch'; + my $del; + if (!defined $q->param('delete')) { + foreach my $put (@{$queryhash{'putData'}}) { + my ($key, $value) = split(/=/, $put, 2); + if ($key eq 'delete') { + $del = 1; + } + } + } + + if (defined $q->param('delete') || defined $del) { + push @args, '-d'; + push @args, $condition; + push @args, $table; + } + elsif (defined $condition) { + push @args, $condition; + if ($q->param('value')) { + for ($q->param('value')) { + push @args, "$table.$_"; + } + } + else { + @args = (@args, @vals); + } + } + else { + foreach (@$entries) { + push @args, split(/ /,$_); + } + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + return @responses; +} + +my @accountFields = ('key', 'username', 'password', 'cryptmethod', 'comments', 'disable'); + +#done aside from being able to change cluster users, which xcat can't do yet +sub accountsHandler { + my @responses; + my @args; + my $key = $q->param('key'); + + if (isGet()) { + + #passwd table + if (!defined $q->param('clusterUser')) { + if (defined $key) { + $request->{command} = 'gettab'; + push @args, "key=$key"; + if (defined $q->param('field')) { + foreach ($q->param('field')) { + push @args, "passwd.$_"; + } + } + else { + foreach (@accountFields) { + push @args, "passwd.$_"; + } + } + } + else { + $request->{command} = 'tabdump'; + push @args, 'passwd'; + } + } + + #cluster user list + else { + $request->{command} = 'xcatclientnnr'; + push @args, 'clusteruserlist'; + push @args, '-p'; + } + } + elsif (isPost()) { + if (!defined $q->param('clusterUser')) { + if (defined $key) { + $request->{command} = 'tabch'; + push @args, "key=$key"; + for ($q->param) { + if ($_ !~ /key/) { + push @args, "passwd.$_=" . $q->param($_); + } + } + } + else { + addPageContent("The key must be specified when creating a non-cluster user"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + + #active directory user + else { + if (defined $q->param('userName') && defined $q->param('userPass')) { + $request->{command} = 'xcatclientnnr'; + push @args, 'clusteruseradd'; + push @args, $q->param('userName'); + push @{$request->{arg}}, @args; + $request->{environment} = {XCAT_USERPASS => $q->param('userPass')}; + } + else { + addPageContent("The key must be specified when creating a cluster user"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + } + elsif (isDelete()) { + if (!defined $q->param('clusterUser')) { + + #just allowing a delete by key at the moment, could expand this to anything + if (defined $key) { + $request->{command} = 'tabch'; + push @args, '-d'; + push @args, "key=$key"; + push @args, "passwd"; + } + else { + addPageContent("The key must be specified when deleting a non-cluster user"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + else { + if (defined $q->param('userName')) { + $request->{command} = 'xcatclientnnr'; + push @args, 'clusteruserdel'; + push @args, $q->param('userName'); + } + else { + addPageContent("The userName must be specified when deleting a cluster user"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + } + elsif (isPut() || isPatch()) { + if (!defined $q->param('clusterUser')) { + if (defined $key) { + $request->{command} = 'tabch'; + push @args, "key=$key"; + for ($q->param) { + if ($_ !~ /key/) { + push @args, "passwd.$_=" . $q->param($_); + } + } + } + else { + addPageContent("The key must be specified when updating a non-cluster user"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + + #TODO: there isn't currently a way to update cluster users + else { + + } + } + else { + unsupportedRequestType(); + exit(0); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + return @responses; +} + +sub objectsHandler { + my @responses; + my @args; + my @objectTypeList = ( + "auditlog", "boottarget", "eventlog", "firmware", "group", "monitoring", + "network", "node", "notification", "osimage", "policy", "route", + "site"); + + #my %objectTypes; + #foreach my $item (@objectTypeList) { $objectTypes{$item} = 1 } + my @objectTypes; + my @objects; + if (defined $path[1]) { + $objectTypes[0] = $path[1]; + if (defined $path[2]) { + $objects[0] = $path[2]; + } + } + if (defined $q->param('objectType')) { + @objectTypes = $q->param('objectType'); + } + if (defined $q->param('object')) { + @objects = $q->param('object'); + } + + if ($q->param('verbose')) { + push @args, '-v'; + } + + if (isGet()) { + if (defined $objectTypes[0]) { + $request->{command} = 'lsdef'; + push @args, '-l'; + push @args, '-t'; + push @args, join(',', @objectTypes); + if (defined $objects[0]) { + push @args, '-o'; + push @args, join(',', @objects); + } + if ($q->param('info')) { + push @args, '-h'; + } + } + else { + if ($q->param('info')) { + push @args, '-h'; + } + else { + + #couldn't find a way to do this through xcatd, so shortcutting the request + my %resp = (data => \@objectTypeList); + return (\%resp); + } + } + } + elsif (isPut()) { + $request->{command} = 'chdef'; + if ($q->param('verbose')) { + push @args, '-v'; + } + if (!defined $q->param('objectType')) { + addPageContent("The object must be specified."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + else { + push @args, '-t'; + push @args, join(',', $q->param('objectType')); + } + if ($q->param('objectName')) { + push @args, join(',', $q->param('objectName')); + } + if ($q->param('dynamic')) { + push @args, '-d'; + } + if ($q->param('minus')) { + push @args, '-m'; + } + if ($q->param('plus')) { + push @args, '-p'; + } + if (defined $q->param('field')) { + foreach ($q->param('field')) { + + #if it has ==, !=. =~ or !~ operators in the field, use the -w option + if (/==|!=|=~|!~/) { + push @args, '-w'; + } + push @args, $_; + } + } + if ($q->param('nodeRange')) { + push @args, $q->param('nodeRange'); + } + + } + elsif (isPost()) { + $request->{command} = 'mkdef'; + if ($q->param('verbose')) { + push @args, '-v'; + } + if (!defined $q->param('objectType')) { + addPageContent("The object must be specified."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + else { + push @args, '-t'; + push @args, join(',', $q->param('objectType')); + } + if ($q->param('objectName')) { + push @args, join(',', $q->param('objectName')); + } + if ($q->param('dynamic')) { + push @args, '-d'; + } + if ($q->param('force')) { + push @args, '-f'; + } + if (defined $q->param('field')) { + foreach ($q->param('field')) { + + #if it has ==, !=. =~ or !~ operators in the field, use the -w option + if (/==|!=|=~|!~/) { + push @args, '-w'; + } + push @args, $_; + } + } + if ($q->param('nodeRange')) { + push @args, $q->param('nodeRange'); + } + + } + elsif (isDelete()) { + $request->{command} = 'rmdef'; + if (defined $q->param('info')) { + push @args, '-h'; + } + elsif (defined $q->param('all')) { + push @args, '-a'; + } + elsif (defined $objectTypes[0]) { + push @args, '-t'; + push @args, join(',', @objectTypes); + if (defined $objects[0]) { + push @args, '-o'; + push @args, join(',', @objects); + } + } + else { + addPageContent( +"Either the help info must be requested or the object must be specified or the flag that indicates everything should be removed." + ); + sendResponseMsg($STATUS_BAD_REQUEST); + } + if (defined $q->param('nodeRange')) { + push @args, $q->param('nodeRange'); + } + } + else { + unsupportedRequestType(); + exit(); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + return @responses; +} + +#complete i think, tho chvm could handle args better +sub vmsHandler { + my @args; + my $noderange; + my $subResource; + if (defined $path[1]) { + $noderange = $path[1]; + $request->{noderange} = $noderange; + } + else { + addPageContent("Invalid nodes and/or groups in noderange"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if (isGet()) { + $request->{command} = 'lsvm'; + if (defined $q->param('all')) { + push @args, '-a'; + } + + # for z/VM + if (defined $q->param('networknames')) { + push @args, '--getnetworknames'; + } + + if (defined $q->param('network')) { + push @args, '--getnetwork'; + push @args, $q->param('getnetwork'); + } + + if (defined $q->param('diskpoolnames')) { + push @args, '--diskpoolnames'; + } + + if (defined $q->param('diskpool')) { + push @args, '--diskpool'; + push @args, $q->param('diskpool'); + } + + if (defined $q->param('checknics')) { + push @args, '--checknics'; + push @args, $q->param('checknics'); + } + } + elsif (isPost()) { + my $entries; + my %entryhash; + my $position; + $request->{command} = 'mkvm'; + unless ($q->param('POSTDATA')) { + addPageContent("Invalid Parameters"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + #collect all parameters from the postdata + $entries = JSON::decode_json($q->param('POSTDATA')); + if (scalar(@$entries) < 1) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + extractData(\%entryhash, $entries); + + # For zVM; clonefrom must be first so that the mkvm call + # has the clone from node in correct spot in makeVM args + if (defined $entryhash{'clonefrom'}) { + push @args, $entryhash{'clonefrom'}; + } + + #for system p + if (defined $entryhash{'cec'}) { + push @args, '-c'; + push @args, $entryhash{'cec'}; + } + + if (defined $entryhash{'startId'}) { + push @args, '-i'; + push @args, $entryhash{'startId'}; + } + + if (defined $entryhash{'source'}) { + push @args, '-l'; + push @args, $entryhash{'source'}; + } + + if (defined $entryhash{'profile'}) { + push @args, '-p'; + push @args, $entryhash{'profile'}; + } + + if (defined $entryhash{'full'}) { + push @args, '--full'; + } + + #for KVM & Vmware + if (defined $entryhash{'master'}) { + push @args, '-m'; + push @args, $entryhash{'master'}; + } + + if (defined $entryhash{'disksize'}) { + push @args, '-s'; + push @args, $entryhash{'disksize'}; + } + + if (defined $entryhash{'memory'}) { + push @args, '--mem'; + push @args, $entryhash{'memory'}; + } + + if (defined $entryhash{'cpu'}) { + push @args, '--cpus'; + push @args, $entryhash{'cpu'}; + } + + if (defined $entryhash{'force'}) { + push @args, '-f'; + } + + # for z/VM + if (defined $entryhash{'userid'}) { + push @args, '--userid'; + push @args, $entryhash{'userid'}; + } + + if (defined $entryhash{'size'}) { + push @args, '--size'; + push @args, $entryhash{'size'}; + } + + if (defined $entryhash{'password'}) { + push @args, '--password'; + push @args, $entryhash{'password'}; + } + + if (defined $entryhash{'privilege'}) { + push @args, '--privilege'; + push @args, $entryhash{'privilege'}; + } + + if (defined $entryhash{'diskpool'}) { + push @args, '--diskpool'; + push @args, $entryhash{'diskpool'}; + } + + if (defined $entryhash{'diskvdev'}) { + push @args, '--diskVdev'; + push @args, $entryhash{'diskvdev'}; + } + if (defined $entryhash{'imagename'}) { + push @args, '--imagename'; + push @args, $entryhash{'imagename'}; + } + if (defined $entryhash{'osimage'}) { + push @args, '--osimage'; + push @args, $entryhash{'osimage'}; + } + if (defined $entryhash{'ipl'}) { + push @args, '--ipl'; + push @args, $entryhash{'ipl'}; + } + # For the mkvm call the zvm.pm code is looking for key=value + # for pool and pw; rather than a "--key value" + if ( defined $entryhash{'pool'} ) { + push @args, "pool=$entryhash{'pool'}"; + } + if ( defined $entryhash{'pw'} ) { + push @args, "pw=$entryhash{'pw'}"; + } + } + elsif (isPut()) { + $request->{command} = 'chvm'; + if ($q->param('PUTDATA')) { + my $entries = JSON::decode_json($q->param('PUTDATA')); + if (scalar(@$entries) < 1) { + addPageContent("No Field and Value map was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + foreach (@$entries) { + # Handle blank delimited parameters + push @args, split(/ /,$_); + } + } + else { + addPageContent("No Field and Value map was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + } + elsif (isDelete()) { + $request->{command} = 'rmvm'; + if (defined $q->param('retain')) { + push @args, '-r'; + } + if (defined $q->param('service')) { + push @args, '--service'; + } + } + else { + unsupportedRequestType(); + exit(); + } + + # Note: MUST parse these parameters after all others if we want to avoid + # duplicating this code on each if branch, since + # lsvm depends on its "subcommand" being the first parameter. + # TODO if we add these parameters to other paths, could we use a subroutine instead? only 2 inputs. + + # Parse the optional upstream object ID, e.g. an OpenStack nova instance UUID + if (defined $queryhash{'objectid'}) { + push @args, '--objectid'; + push @args, $queryhash{'objectid'}->[0]; + } + + # Parse the optional upstream request ID, e.g. an OpenStack request UUID + if (defined $queryhash{'requestid'}) { + push @args, '--requestid'; + push @args, $queryhash{'requestid'}->[0]; + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + my @responses = sendRequest($req); + return @responses; +} + +sub versionHandler { + $request->{command} = "lsxcatd"; + push @{$request->{arg}}, "-v"; + my $req = genRequest(); + my @responses = sendRequest($req); + return @responses; +} + +#for operations that take a 'long' time to finish, this will provide the interface to check their status +sub jobsHandler { + +} + +sub hypervisorHandler { + my @responses; + my @args; + if (isPut()) { + my %entryhash; + if (defined $path[1]) { + $request->{noderange} = $path[1]; + } + else { + addPageContent("Invalid nodes and/or groups in node in noderange"); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + if (defined $path[2]) { + $request->{command} = $path[2]; + } + else { + $request->{command} = 'chhypervisor'; + } + my $entries = JSON::decode_json( $q->param('PUTDATA') ); + if (scalar(@$entries) < 1) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + foreach (@$entries) { + push @args, split(/ /,$_); + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + return @responses; + } +} + +sub debugHandler { + my @responses; + my @args; + if (isPut()) { + my %entryhash; + $request->{command} = 'xcatclientnnr xcatdebug'; + + #push @args, 'xcatdebug'; + my $entries = JSON::decode_json( $q->param('PUTDATA') ); + if (scalar(@$entries) < 1) { + addPageContent("No set attribute was supplied."); + sendResponseMsg($STATUS_BAD_REQUEST); + } + + foreach (@$entries) { + push @{$request->{arg}}, $_; + } + + push @{$request->{arg}}, @args; + my $req = genRequest(); + @responses = sendRequest($req); + return @responses; + } +} + +#all data wrapping and writing is funneled through here +sub wrapData { + my $data = shift; + my $errorInformation = ''; + + #trim the serverdone message off + if (exists $data->[0]->{serverdone} && exists $data->[0]->{error}) { + $errorInformation = $data->[0]->{error}->[0]; + addPageContent($q->p($errorInformation)); + if (($errorInformation =~ /Permission denied/) || ($errorInformation =~ /Authentication failure/)) { + sendResponseMsg($STATUS_UNAUTH); + } + else { + sendResponseMsg($STATUS_FORBIDDEN); + } + exit 1; + } + else { + pop @{$data}; + } + if (exists $formatters{$format}) { + $formatters{$format}->($data); + } + + #all information were add into the global varibale, call the response funcion + if (exists $data->[0]->{info} && $data->[0]->{info}->[0] =~ /Could not find an object/) { + sendResponseMsg($STATUS_NOT_FOUND); + } + elsif (isPost()) { + sendResponseMsg($STATUS_CREATED); + } + else { + sendResponseMsg($STATUS_OK); + } +} + +sub wrapJson { + my $data = shift; + my $json; + $json->{'data'} = $data; + addPageContent(JSON::to_json($json)); +} + +sub wrapHtml { + my $item; + my $response = shift; + my $baseUri = $url . $pathInfo; + if ($baseUri !~ /\/^/) { + $baseUri .= "/"; + } + + foreach my $element (@$response) { + + #foreach my $element (@$data){ + #if($element->{error}){ + if ($element->{node}) { + addPageContent(""); + foreach $item (@{$element->{node}}) { + + #my $url = $baseUri.$item->{name}[0]; + addPageContent(""); + if (exists $item->{data} && exists $item->{data}[0]) { + if (ref($item->{data}[0]) eq 'HASH') { + if (exists $item->{data}[0]->{desc} && exists $item->{data}[0]->{desc}[0]) { + addPageContent(""); + } + if (ref($item->{data}[0]) eq 'HASH' && exists $item->{data}[0]->{contents}[0]) { + addPageContent(""); + } + } + else { + addPageContent(""); + } + } + elsif (exists $item->{error}) { + addPageContent(""); + } + addPageContent(""); + } + addPageContent("
                                  $item->{name}[0]$item->{data}[0]->{desc}[0]$item->{data}[0]->{contents}[0]$item->{data}[0]$item->{error}[0]
                                  "); + } + if ($element->{data}) { + addPageContent(""); + foreach $item (@{$element->{data}}) { + my @values = split(/:/, $item, 2); + addPageContent(""); + foreach (@values) { + if ($formatType =~ /splitCommas/) { + my @fields = split(/,/, $_, -1); + foreach (@fields) { + addPageContent(""); + } + } + else { + addPageContent(""); + } + } + addPageContent("\n"); + } + addPageContent("
                                  $_$_
                                  "); + } + if ($element->{info}) { + addPageContent(""); + foreach $item (@{$element->{info}}) { + addPageContent(""); + my $fieldname = ''; + my $fieldvalue = ''; + + #strip whitespace in the string + $item =~ s/^\s+//; + $item =~ s/\s+$//; + if ($item =~ /Object/) { + ($fieldname, $fieldvalue) = split(/:/, $item); + } + elsif ($item =~ /.*=.*/) { + my $position = index $item, '='; + $fieldname = substr $item, 0, $position; + $fieldvalue = substr $item, $position + 1; + } + else { + $fieldname = $item; + } + addPageContent(""); + if ($fieldvalue ne '') { + addPageContent(""); + } + addPageContent("\n"); + } + addPageContent("
                                  " . $fieldname . "" . $fieldvalue . "
                                  "); + } + if ($element->{error}) { + addPageContent(""); + foreach $item (@{$element->{error}}) { + addPageContent(""); + } + addPageContent("
                                  " . $item . "
                                  "); + } + } +} + +sub wrapXml { + my @data = shift; + foreach (@data) { + foreach (@$_) { + addPageContent(XMLout($_, RootName => '', NoAttr => 1, KeyAttr => [])); + } + } +} + +#general tests for valid requests and responses with HTTP codes here +if (!doesResourceExist($resource)) { + addPageContent("Resource '$resource' does not exist"); + sendResponseMsg($STATUS_NOT_FOUND); +} +else { + if ($DEBUGGING) { + addPageContent($q->p("resource is $resource")); + } + handleRequest(); +} + +#talk to the server +use Socket; +use IO::Socket::INET; +use IO::Socket::SSL; + +# The database initialization may take some time in the system boot scenario +# wait for a while for the database initialization +#do we really need to do this for the web service? sub sendRequest { my $request = shift; - my $xmlinoptions = shift; # optional arg to not set ForceArray on the XMLin() call my $sitetab; my $retries = 0; - if ($DEBUGGING == 2) { + if ($DEBUGGING) { my $preXml = $request; - $preXml =~ s/< /g; - $preXml =~ s/>/>
                                  /g; - addPageContent($q->p("DEBUG: request XML: " . $request . "\n")); + + #$preXml =~ s/< /g; + #$preXml =~ s/>/>
                                  /g; + addPageContent($q->p("request XML
                                  " . $preXml)); } #hardcoded port for now @@ -3217,60 +2408,53 @@ sub sendRequest { my $client; if (-r $keyfile and -r $certfile and -r $cafile) { $client = IO::Socket::SSL->new( - PeerAddr => $xcatHost, - SSL_key_file => $keyfile, - SSL_cert_file => $certfile, - SSL_ca_file => $cafile, - SSL_verify_mode => SSL_VERIFY_PEER, - SSL_verifycn_scheme => "none", - SSL_use_cert => 1, - Timeout => 15,); + PeerAddr => $xcatHost, + SSL_key_file => $keyfile, + SSL_cert_file => $certfile, + SSL_ca_file => $cafile, + SSL_use_cert => 1, + Timeout => 15,); } else { $client = IO::Socket::SSL->new( - PeerAddr => $xcatHost, - SSL_verify_mode => 0, - Timeout => 15,); + PeerAddr => $xcatHost, + SSL_verify_mode => 'SSL_VERIFY_NONE', + Timeout => 15,); } unless ($client) { if ($@ =~ /SSL Timeout/) { - error("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat", $STATUS_TIMEOUT); + addPageContent("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat"); + sendResponseMsg($STATUS_TIMEOUT); } else { - error("Connection failurexx: $@", $STATUS_SERVICE_UNAVAILABLE); + addPageContent("Connection failurexx: $@"); + sendResponseMsg($STATUS_SERVICE_UNAVAILABLE); } } - debug("request xml=$request"); print $client $request; my $response; my $rsp; - my $fullResponse = []; - my $cleanexit = 0; + my @fullResponse; + my $cleanexit = 0; while (<$client>) { $response .= $_; if (m/<\/xcatresponse>/) { #replace ESC with xxxxESCxxx because XMLin cannot handle it if ($DEBUGGING) { - - #addPageContent("DEBUG: response from xcatd: " . $response . "\n"); + addPageContent($response . "\n"); } $response =~ s/\e/xxxxESCxxxx/g; - debug("response xml=$response"); - #bmp: i added the $xmlinoptions var because for the table output it saved me processing if everything - # wasn't forced into arrays. Consider if that could save you processing on other api calls too. - if (!$xmlinoptions) { $xmlinoptions = { SuppressEmpty => undef, ForceArray => 1 }; } - $rsp = XML::Simple::XMLin($response, %$xmlinoptions); - - #debug(Dumper($rsp)); + #print "responseXML is ".$response; + $rsp = XMLin($response, SuppressEmpty => undef, ForceArray => 1); #add ESC back foreach my $key (keys %$rsp) { if (ref($rsp->{$key}) eq 'ARRAY') { - foreach my $text (@{ $rsp->{$key} }) { + foreach my $text (@{$rsp->{$key}}) { next unless defined $text; $text =~ s/xxxxESCxxxx/\e/g; } @@ -3281,175 +2465,57 @@ sub sendRequest { } $response = ''; - push(@$fullResponse, $rsp); - if (exists($rsp->{serverdone})) { + push(@fullResponse, $rsp); + if ($rsp->{serverdone}) { $cleanexit = 1; last; } } } unless ($cleanexit) { - error("communication with the xCAT server seems to have been ended prematurely", $STATUS_SERVICE_UNAVAILABLE); + addPageContent("ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely"); + sendResponseMsg($STATUS_SERVICE_UNAVAILABLE); + exit(0); } - if ($DEBUGGING == 2) { - addPageContent($q->p("DEBUG: full response from xcatd: " . Dumper($fullResponse))); + if ($DEBUGGING) { + addPageContent($q->p("response " . Dumper(@fullResponse))); } - return $fullResponse; + return @fullResponse; } -# Put input parameters from both $q->url_param and put/post data (if it exists) into generalparams and paramhash for all to use -# 1st output param - The params which are listed in @generalparamlis as a general parameters like 'debug=1, pretty=1' -# 2nd output param - All the params from url params and 'PUTDATA'/'POSTDATA' except the ones in @generalparamlis -sub fetchParameters { - my @generalparamlist = qw(userName userPW pretty debug xcoll); - - # 1st check for put/post data and put that in the hash - my $pdata; - if (isPut()) { - $pdata = $q->param('PUTDATA'); - - # in the sles 11.x, the 'PUTDATA' param is not supported for PUT method - # so we have to work around it by getting it by myself - unless ($pdata) { - if (-f "/etc/SuSE-release") { # SUSE os - if ($ENV{'CONTENT_TYPE'} =~ /json/) { - $q->read_from_client(\$pdata, $ENV{'CONTENT_LENGTH'}); - } - } - } - } elsif (isPost()) { - $pdata = $q->param('POSTDATA'); - } elsif (isDelete() || isGET()) { - if ($ENV{'CONTENT_TYPE'} =~ /json/) { - $q->read_from_client(\$pdata, $ENV{'CONTENT_LENGTH'}); - } - } - - if ($dbgdata) { - $pdata = $dbgdata; - } - - my $genparms = {}; - my $phash; - if ($pdata) { - $phash = eval { $JSON->decode($pdata); }; - if ($@) { - - # remove the code location information to make the output looks better - if ($@ =~ m/ at \//) { - $@ =~ s/ at \/.*$//; - } - error("$@", $STATUS_BAD_REQUEST); - } - - #debug("phash=" . Dumper($phash)); - if (ref($phash) ne 'HASH') { error("put or post data must be a json object (hash/dict).", $STATUS_BAD_REQUEST); } - - # if any general parms are in the put/post data, move them to genparms - foreach my $k (keys %$phash) { - if (grep(/^$k$/, @generalparamlist)) { - $genparms->{$k} = $phash->{$k}; - delete($phash->{$k}); - } - } - } - else { $phash = {}; } - - # now get params from the url (if any of the keys overlap, the url value will overwrite the put/post value) - foreach my $p ($q->url_param) { - my @a = $q->url_param($p); # this could be a single value or an array, have to figure it out - my $value; - if (scalar(@a) > 1) { $value = [@a]; } # convert it to a reference to an array - else { $value = $a[0]; } - if (grep(/^$p$/, @generalparamlist)) { $genparms->{$p} = $value; } - else { $phash->{$p} = $value; } - } - - return ($genparms, $phash); +sub isGet { + return uc($requestType) eq "GET"; } -# Load the XML::Simple module -sub loadXML { - if ($xmlinstalled) { return; } - - $xmlinstalled = eval { require XML::Simple; }; - unless ($xmlinstalled) { - error('The XML::Simple perl module is missing. Install perl-XML-Simple before using the xCAT REST web services API with this format."}', $STATUS_SERVICE_UNAVAILABLE); - } - $XML::Simple::PREFERRED_PARSER = 'XML::Parser'; +sub isPut { + return uc($requestType) eq "PUT"; } -# Load the JSON perl module, if not already loaded. Sets the $JSON global var. -sub loadJSON { - if ($JSON) { return; } # already loaded - # require JSON dynamically and let them know if it is not installed - my $jsoninstalled = eval { require JSON; }; - unless ($jsoninstalled) { - error("JSON perl module missing. Install perl-JSON before using the xCAT REST web services API.", $STATUS_SERVICE_UNAVAILABLE); - } - $JSON = JSON->new(); +sub isPost { + return uc($requestType) eq "POST"; } -# add a error msg to the output in the correct format and end this request -sub error { - my ($errmsg, $httpcode, $errorcode) = @_; - my $json; - $json->{error} = $errmsg; - $json->{errorcode} = '2'; - if ($errorcode) { - $json->{errorcode} = $errorcode; +sub isPatch { + return uc($requestType) eq "PATCH"; +} + +sub isDelete { + return uc($requestType) eq "DELETE"; +} + +#check to see if this is a valid user. userName and password are already set +sub isAuthenticUser { + $request->{command} = 'authcheck'; + my $req = genRequest(); + my @responses = sendRequest($req); + if ($responses[0]->{data}[0] eq "Authenticated") { + + #user is authenticated + return 1; } - addPageContent($JSON->encode($json)); - sendResponseMsg($httpcode); + #authentication failure + addPageContent($responses[0]->{error}[0]); + sendResponseMsg($STATUS_UNAUTH); } - - -# if debugging, output the given string -sub debug { - if (!$DEBUGGING) { return; } - addPageContent($q->p("DEBUG: $_[0]\n")); -} - -# when having bugs that cause this cgi to not produce any output, output something and then exit. -sub debugandexit { - debug("$_[0]\n"); - sendResponseMsg($STATUS_OK); -} - -sub displaydebugmsg { - addPageContent($q->p("DEBUG: generalparams:" . Dumper($generalparams))); - addPageContent($q->p("DEBUG: paramhash:" . Dumper($paramhash))); - addPageContent($q->p("DEBUG: q->request_method: $requestType\n")); - - #addPageContent($q->p("DEBUG: q->user_agent: $userAgent\n")); - addPageContent($q->p("DEBUG: pathInfo: $pathInfo\n")); - - #addPageContent($q->p("DEBUG: path " . Dumper(@path) . "\n")); - #foreach (keys(%ENV)) { addPageContent($q->p("DEBUG: ENV{$_}: $ENV{$_}\n")); } - #addPageContent($q->p("DEBUG: userName=".$paramhash->{userName}.", password=".$paramhash->{password}."\n")); - #addPageContent($q->p("DEBUG: http() values:\n" . http() . "\n")); - #if ($pdata) { addPageContent($q->p("DEBUG: pdata: $pdata\n")); } - addPageContent("\n"); - if ($DEBUGGING == 3) { - sendResponseMsg($STATUS_OK); # this will also exit - } -} - - -# push flags (options) onto the xcatd request. Arguments: request args array, flags array. -# Format of flags array: -# Use this function for cmds with a lot of flags like xdcp and xdsh -sub pushFlags { - my ($args, $flags) = @_; - foreach my $f (@$flags) { - my ($key, $flag, $arg) = @$f; - if (defined($paramhash->{$key})) { - push @$args, $flag; - if ($arg) { push @$args, $paramhash->{$key}; } - } - } -} - - diff --git a/xCAT/xCAT.spec b/xCAT/xCAT.spec index 2b30241c5..eb28babd9 100644 --- a/xCAT/xCAT.spec +++ b/xCAT/xCAT.spec @@ -28,9 +28,12 @@ Conflicts: xCATsn Requires: perl-DBD-SQLite Requires: xCAT-client = 4:%{version}-%{release} Requires: xCAT-server = 4:%{version}-%{release} + +%ifnarch s390x Requires: xCAT-probe = 4:%{version}-%{release} Requires: xCAT-genesis-scripts-x86_64 = 1:%{version}-%{release} Requires: xCAT-genesis-scripts-ppc64 = 1:%{version}-%{release} +%endif %define pcm %(if [ "$pcm" = "1" ];then echo 1; else echo 0; fi) %define notpcm %(if [ "$pcm" = "1" ];then echo 0; else echo 1; fi) @@ -86,8 +89,10 @@ Requires: ipmitool-xcat >= 1.8.17-1 %if %notpcm # PCM does not need or ship syslinux-xcat +%ifnarch s390x Requires: syslinux-xcat %endif +%endif %description xCAT is a server management package intended for at-scale management, including