'Discover Hardware', 'patterns' => 'Cluster Patterns', 'patterns1b' => 'Switch Ports', 'patterns2' => 'More Cluster Patterns', 'preparemn' => 'Prepare Management Node', 'prediscover' => 'Power On Hardware', 'discover' => 'Discover HW Control Points', 'updatedefs' => 'Update Definitions', 'configurehcps' => 'Configure HW Control Points', 'createnodes' => 'Create Nodes', /* 'testhcps' => 'Test HW Control', */ 'done' => 'Complete', ); if (isset($_REQUEST['page'])) { displayWizard($pages); } else { // initial display of the wizard, show the whole page insertHeader('Discover New Nodes', array('discover.css',"$TOPDIR/lib/wizard.css"), array("$TOPDIR/lib/wizard.js"), array('machines','discover')); echo "
\n"; displayWizard($pages); echo "
\n"; // end the content div insertFooter(); } //----------------------------------------------------------------------------- // Save the values sent up from the previous wizard page into the session. function savePostVars() { foreach ($_POST as $k => $v) { if ($k != 'action' && $k != 'page') { $_SESSION[$k] = $v; } } } //----------------------------------------------------------------------------- // Expand the noderange for non-existing nodes function expandNR($nr) { //todo: use xcatd to expand this. Change xcatd around line 998: } elsif ($req->{command}->[0] eq "noderange" and $req->{noderange}) { // see pping as an example of the client/server for noderange expansion $a = array(); if (empty($nr)) return $a; list($begin, $end) = explode('-', $nr); $begParts = array(); if (!preg_match('/^(\D+)(\d+)$/', $begin, $begParts)) { msg('E',"Error in noderange syntax: $nr"); return NULL; } $endParts = array(); if (!preg_match('/^(\D+)(\d+)$/', $end, $endParts)) { msg('E',"Error in noderange syntax: $nr"); return NULL; } if ($begParts[1] != $endParts[1]) { msg('E',"Error in noderange syntax: $nr"); return NULL; } $numlen = strlen($begParts[2]); for ($i=$begParts[2]; $i<=$endParts[2]; $i++) { $istr = "$i"; if (strlen($istr) < $numlen) { $istr = substr('000000',0,$numlen-strlen($istr)) . $istr; } $a[] = "$begParts[1]$istr"; } return $a; } //----------------------------------------------------------------------------- function intro($action, $step) { echo "

This wizard will guide you through the process of defining the naming conventions within your cluster, discovering the hardware on your network, and automatically defining it in the xCAT database."; echo " Choose which type of hardware you want to discover, and then click Next.

\n"; // The least hacky way to get this list left justified, but have the block in the center, is to use a table. CSS snobs, just deal with it. echo "
    \n"; echo "
  • \n"; echo "
  • \n"; echo "
\n"; } //----------------------------------------------------------------------------- function patterns($action, $step) { echo "
\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "

Switch Patterns

HMCs

Frame (BPA) Patterns

Drawer (FSP/CEC) Patterns

\n"; //todo: get HCP userids/pws from the user } //----------------------------------------------------------------------------- function patterns1b($action, $step) { //todo: do validation of all pages that have input savePostVars(); // Figure out how many switches there need to be $hmcs = expandNR($_SESSION['hmcHostname']); $bpas = expandNR($_SESSION['bpaHostname']); $fsps = expandNR($_SESSION['fspHostname']); //echo "

", implode(',',$hmcs), "

\n"; $total = count($hmcs) + count($bpas) + count($fsps); if (!$_SESSION['portsPerSwitch']) { $numswitches = 1; } else { $numswitches = (integer) ((($total-1) / $_SESSION['portsPerSwitch']) + 1); } //echo "

$numswitches

\n"; echo "
\n"; echo "\n"; $switches = expandNR($_SESSION['switchHostname']); //todo: if count($switches) != $numswitches, then we have a problem foreach ($switches as $k => $sw) { $num = $k + 1; echo "\n"; } echo "\n"; echo "\n"; echo "

Switch Port Assignments

Discovery Information

\n"; } //----------------------------------------------------------------------------- function patterns2($action, $step) { savePostVars(); echo "
\n"; // For now, many of the BB fields are disabled echo "\n"; echo "\n"; echo ""; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "

Building Blocks

(Subnet address for nodes in each Building Block)

LPAR Information

\n"; // do we need to get any info about the resources that should be in each lpar, or do we just divide them evenly? } //----------------------------------------------------------------------------- function preparemn($action, $step) { global $TOPDIR; if ($step == 0) { savePostVars(); insertProgressTable(array('Write xCAT switch table.', 'Write xCAT hosts table.', 'Define networks.', 'Configure DHCP.', )); if ($action != 'back') { echo ""; } } elseif ($step == 1) { writeSwitchTable($step); } elseif ($step == 2) { writeHostsTable($step); } elseif ($step == 3) { setDynRange($_SESSION["dynamicIP"], $step); } elseif ($step == 4) { makedhcp($step); } } //----------------------------------------------------------------------------- // Using the hcp and switch ranges, write out the switch table //todo: maybe should not use tabrestore in case we are just discovery additional hw function writeSwitchTable($step) { $hmcs = expandNR($_SESSION['hmcHostname']); $bpas = expandNR($_SESSION['bpaHostname']); $fsps = expandNR($_SESSION['fspHostname']); $switches = expandNR($_SESSION['switchHostname']); $numports = $_SESSION['portsPerSwitch']; $data = array(array('#node,switch,port,vlan,interface,comments,disable')); //echo "

\n"; foreach ($switches as $k => $sw) { $num = $k + 1; $sequence = $_SESSION["switchSequence$num"]; $seq = preg_split('/[\s,]+/', $sequence); $port = 1; foreach ($seq as $s) { // each $s is something like: FSP:5 list($type, $num) = explode(':', $s); if (preg_match('/^hmc$/i',$type)) $ar=&$hmcs; elseif (preg_match('/^bpa$/i',$type)) $ar=&$bpas; elseif (preg_match('/^fsp$/i',$type)) $ar=&$fsps; else { msg('E', "Invalid HW control point type in $s"); return; } if ($num == '*') { $num = count($ar); } for ($i=1; $i<=$num; $i++) { $node = array_shift($ar); $data[] = array($node,$sw,$port); /* $xml = docmd('nodeadd',NULL,array($node,'groups=all',"switch.node=$node","switch.switch=$sw","switch.port=$port")); if (getXmlErrors($xml,$errors)) { msg('E',"nodeadd failed: " . implode(' ',$errors)); return; } else { echo "Wrote: $node,$sw,$port
\n"; }*/ if (++$port > $numports) break 2; } } } //echo "

\n"; ob_flush(); flush(); //array_unshift($data, array('#node,switch,port,vlan,interface,comments,disable')); $xml = doTabrestore('switch', $data); //$errors = array(); if (getXmlErrors($xml,$errors)) { msg('E',"tabrestore switch failed: " . implode(' ',$errors)); return; } // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => '')); } //----------------------------------------------------------------------------- // Using the hcp ranges, write out the hosts table function writeHostsTable($step) { $machines = array(); $machines[$_SESSION['switchIP']] = expandNR($_SESSION['switchHostname']); $machines[$_SESSION['hmcIP']] = expandNR($_SESSION['hmcHostname']); $machines[$_SESSION['bpaIP']] = expandNR($_SESSION['bpaHostname']); $machines[$_SESSION['fspIP']] = expandNR($_SESSION['fspHostname']); $machines[$_SESSION['subnet']] = expandNR($_SESSION['computeNodename']); $data = array(array('#node,ip,hostnames,comments,disable')); //echo "

\n"; foreach ($machines as $ip => $ar) { // this loop goes thru each type of hw foreach ($ar as $hostname) { // this loop goes thru each of the hostnames for that type of hw $data[] = array($hostname,$ip); //echo "Wrote: $hostname,$ip
\n"; incrementIP($ip); } } //echo "

\n"; ob_flush(); flush(); $xml = doTabrestore('hosts', $data); $errors = array(); if (getXmlErrors($xml,$errors)) { msg('E',"tabrestore hosts failed: " . implode(' ',$errors)); return; } // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => '')); } //----------------------------------------------------------------------------- function incrementIP(& $ip) { $parts = explode('.', $ip); $parts[3]++; if ($parts[3] >= 255) { $parts[2]++; $parts[3] = 1; if ($parts[3] >= 255) { $parts[1]++; $parts[2] = 1; } // assume parts[1] is not 255, because we never increment the 1st field } $ip = implode('.', $parts); } //----------------------------------------------------------------------------- //todo: we need a better way to change the networks table than tabdump/tabrestore. We can not use chtab because its not client/svr. We can not use chdef because there is no netname defined by makenetworks. function setDynRange($range, $step) { // Get the whole table via tabdump $xml = docmd('tabdump','',array('networks')); $data = array(); foreach ($xml->children() as $response) foreach ($response->children() as $line) { $line = (string) $line; if(ereg("^#", $line)) { // handle the header specially $data[] = array($line); continue; } $values = splitTableFields($line); $values[8] = '"' . $range . '"'; // dynamicrange is the 9th field $data[] = $values; } // Now restore that data back into the networks table $xml = doTabrestore('networks', $data); $errors = array(); if (getXmlErrors($xml,$errors)) { msg('E',"tabrestore networks failed: " . implode(' ',$errors)); return; } // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => '')); } //----------------------------------------------------------------------------- function makedhcp($step) { $xml = docmd('makedhcp',NULL,array('-n')); $errors = array(); if (getXmlErrors($xml,$errors)) { msg('E',"makedhcp failed: " . implode(' ',$errors)); return; } // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => TRUE, 'error' => '')); } //----------------------------------------------------------------------------- function prediscover($action, $step) { echo "
\n"; echo "

Do the following manual steps now:

\n"; echo "
  1. Power on all of the HMCs.
  2. \n"; echo "
  3. Then power on all of frames.
  4. \n"; echo "
  5. Then click Next to discover the hardware on the service network.
  6. \n"; echo "
\n"; } //----------------------------------------------------------------------------- function discover($action, $step) { global $TOPDIR; if ($step == 0) { insertProgressTable(array('Discover HMCs, BPAs, and FSPs.')); if ($action != 'back') { echo ""; } } elseif ($step == 1) { lsslp($step); } } //----------------------------------------------------------------------------- //todo: we are just simulating lsslp right now function lsslp($step) { /* todo: show this echo "

"; echo "Discovered HMCs: ", $_SESSION['hmcHostname'], "
\n"; echo "Discovered BPAs: ", $_SESSION['bpaHostname'], "
\n"; echo "Discovered FSPs: ", $_SESSION['fspHostname'], "
\n"; echo "

\n"; */ //$errors = array(); $xml = docmd('nodeadd',NULL,array($_SESSION['hmcHostname'],'groups=hmc,all','nodetype.nodetype=hmc')); if (getXmlErrors($xml,$errors)) { msg('E',"nodeadd hmc failed: " . implode(' ',$errors)); return; } $xml = docmd('nodeadd',NULL,array($_SESSION['bpaHostname'],'groups=bpa,all','nodetype.nodetype=bpa','nodehm.mgt=hmc','nodehm.power=hmc','ppc.comments=bpa','vpd.serial=|(\D+)(\d+)|($2)|','vpd.mtm=|(\D+)(\d+)|($1)|')); if (getXmlErrors($xml,$errors)) { msg('E',"nodeadd bpa failed: " . implode(' ',$errors)); return; } // We are assuming there are 4 fsps in each bpa $xml = docmd('nodeadd',NULL,array($_SESSION['fspHostname'],'groups=fsp,all','nodetype.nodetype=fsp','nodehm.mgt=hmc','nodehm.power=hmc','ppc.id=|\D+(\d+)|((($1-1)%4)+1)|','ppc.parent=|(\D+)(\d+)|b((($2-1)/4)+1)|','vpd.serial=|(\D+)(\d+)|($2)|','vpd.mtm=|(\D+)(\d+)|($1)|')); if (getXmlErrors($xml,$errors)) { msg('E',"nodeadd fsp failed: " . implode(' ',$errors)); return; } /* $xml = docmd('chdef',NULL,array('-t','group','bpa','serial=|(\D+)(\d+)|($2)|','mtm=|(\D+)(\d+)|($1)|')); if (getXmlErrors($xml,$errors)) { msg('E',"chdef bpa failed: " . implode(' ',$errors)); return; } $xml = docmd('chdef',NULL,array('-t','group','fsp','serial=|(\D+)(\d+)|($2)|','mtm=|(\D+)(\d+)|($1)|')); if (getXmlErrors($xml,$errors)) { msg('E',"chdef fsp failed: " . implode(' ',$errors)); return; } */ // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => TRUE, 'error' => '')); } //----------------------------------------------------------------------------- function updatedefs($action, $step) { global $TOPDIR; if ($step == 0) { insertProgressTable(array('Determine which CECs each HMC should manage.', 'Create HW control point node groups.', 'Assign frame numbers.', /* 'Assign supernode numbers and building block numbers.', 'Assign building block subnets.', */ 'Update name resolution.', )); if ($action != 'back') { echo ""; } } elseif ($step == 1) { assigncecs($step); } elseif ($step == 2) { createhcpgroups($step); } elseif ($step == 3) { assignframenums($step); } elseif ($step == 4) { nameres($step); } } //----------------------------------------------------------------------------- function assigncecs($step) { $numCECs = $_SESSION['numCECs']; $hmcs = expandNR($_SESSION['hmcHostname']); $bpas = expandNR($_SESSION['bpaHostname']); $fsps = expandNR($_SESSION['fspHostname']); $h = 0; // start with the 1st hmc $f = 0; $errors = array(); // Go thru the fsps taking groups of numCECs and assigning them to the next hmc while (TRUE) { // Get the next group of fsps $length = min($numCECs, count($fsps)-$f); $fslice = array_slice($fsps, $f, $length); $xml = docmd('nodech',implode(',',$fslice),array("ppc.hcp=$hmcs[$h]")); if (getXmlErrors($xml,$errors)) { msg('E',"nodech fsp failed: " . implode(' ',$errors)); return; } // Decide if we are all out of fsps $h++; $f += $length; if ($h>=count($hmcs) || $f>=count($fsps)) break; } //todo: how do we decide what bpas to assign to which hmcs? // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => '')); } //----------------------------------------------------------------------------- function createhcpgroups($step) { //todo: may need to do this once we are using the real lsslp // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => '')); } //----------------------------------------------------------------------------- // Give frame numbers to each bpa function assignframenums($step) { $errors = array(); $xml = docmd('nodech','bpa',array('ppc.id=|\D+(\d+)|($1)|')); if (getXmlErrors($xml,$errors)) { msg('E',"nodech bpa failed: " . implode(' ',$errors)); return; } // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => '')); } //----------------------------------------------------------------------------- // Run makehosts and makedns function nameres($step) { $errors = array(); $xml = docmd('makehosts',NULL,NULL); if (getXmlErrors($xml,$errors)) { msg('E',"makehosts failed: " . implode(' ',$errors)); return; } $xml = docmd('makedns',NULL,NULL); if (getXmlErrors($xml,$errors)) { msg('E',"makedns failed: " . implode(' ',$errors)); return; } // Send JSON data back to the browser. Todo: handle the errors too. echo json_encode(array('step' => (integer)++$step, 'done' => TRUE, 'error' => '')); } //----------------------------------------------------------------------------- function configurehcps($action, $step) { global $TOPDIR; if ($step == 0) { insertProgressTable(array('Assign CECs to their HMC.', 'Set frame numbers in BPAs.', 'Power on CECs to Standby.', )); if ($action != 'back') { echo ""; } } elseif ($step == 1) { cecs2hmcs($step); } elseif ($step == 2) { setframenum($step); } elseif ($step == 3) { cecs2standby($step); } //todo: set HCP userids/pws } function cecs2hmcs($step) {echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => ''));} function setframenum($step) {echo json_encode(array('step' => (integer)++$step, 'done' => FALSE, 'error' => ''));} function cecs2standby($step) {echo json_encode(array('step' => (integer)++$step, 'done' => TRUE, 'error' => ''));} //----------------------------------------------------------------------------- function createnodes($action, $step) { global $TOPDIR; //todo: need to show progress for each CEC if ($step == 0) { insertProgressTable(array('Create LPARs in each CEC and save node definitions in xCAT database.')); if ($action != 'back') { echo ""; } } elseif ($step == 1) { createlpars($step); } } //----------------------------------------------------------------------------- function createlpars($step) { $numlpars = $_SESSION['numLPARs']; $fsps = expandNR($_SESSION['fspHostname']); $nodes = expandNR($_SESSION['computeNodename']); $samplenode = ''; //todo: ??? $errors = array(); $n = 0; // index into the nodes array foreach ($fsps as $f) { $length = min($numlpars, count($nodes)-$n); $nslice = array_slice($nodes, $n, $length); //todo: actually make the lpars //$xml = docmd('mkvm',NULL,array($samplenode,'-i','1','-n',implode(',',$nslice))); //if (getXmlErrors($xml,$errors)) { msg('E',"mkvm failed: " . implode(' ',$errors)); return; } // Decide if we are all out of nodes $n += $length; if ($n >= count($nodes)) break; } //todo: Change this when mkvm is creating the base node definition. // Also, the following assumes the node range starts with 1 and the fsp node range is simple. // Really need to do individual nodeadd for each node. $parts = array(); preg_match('/^(\D+)/', $_SESSION['fspHostname'], $parts); $fsp = $parts[1]; $xml = docmd('nodeadd',NULL,array($_SESSION['computeNodename'],'groups=lpar,all','nodetype.nodetype=lpar,osi', 'nodehm.mgt=hmc','nodehm.power=hmc','nodehm.cons=hmc','noderes.netboot=yaboot', 'nodetype.arch=ppc64','ppc.id=|\D+(\d+)|((($1-1)%'.$numlpars.')+1)|', 'ppc.parent=|(\D+)(\d+)|'.$fsp.'((($2-1)/'.$numlpars.')+1)|')); if (getXmlErrors($xml,$errors)) { msg('E',"nodeadd nodes failed: " . implode(' ',$errors)); return; } echo json_encode(array('step' => (integer)++$step, 'done' => TRUE, 'error' => '')); } //----------------------------------------------------------------------------- // Currently not used. function testhcps($action, $step) { global $TOPDIR; echo "
\n"; } //----------------------------------------------------------------------------- function done($action, $step) { global $TOPDIR; echo "

Cluster set up successfully completed!

\n"; echo "

You can now view your node definitions and start to deploy nodes.

\n"; } ?>