actual UpdateNode // (POST) node_id=node_id ng_add=nodegroup_id // AddNodeToNodeGroup // (POST) boot_state=boot_state node_id=node_id // (POST) ng_add=nodegroup_id // (*) downloadconf.php // (GET) id=node_id [download=1] // either showed current status, or performed actual config download // in this new version we support only POST behaviour with the following interface // REQUIRED : node_id=node_id // (*) action='prompt-update' : former node_update.php // (*) action='update' // hostname= // model= : actually updated the node // (*) action='boot-state' // boot_state= : changes bootstate // (*) action='delete' : deletes node // (*) action='download-node-floppy' : // (*) action='download-node-iso' : // (*) action='download-node-usb' : // : same as former downloadconf.php with download unset // if in addition POST contains a non-empty field 'download' : // : performs actual node-dep download // (*) action='download-generic-iso': // (*) action='download-generic-usb': // : performs actual generic download // (*) action='add-in-nodegroup': should include this for compatibility, replaces ng_add, // though I could not figure where it's called // TODO : manage a post field for displaying results of previous page // see the special 'flash' in rails // delivering node-dependant images requires larger memory limit // trial and error, based on the current sizes // generic-ISO 43980800 // generic-usb 44720128 // 256M OK // 128M OK // 96M OK // 88M KO // 80M KO // 64M KO // Bottom line is, looks like we need in the order of twice the file size // so let's play it safe // Thierry - for 4.2, we need a larger area, was 100 for 4.1 ini_set("memory_limit","150M"); // Require login require_once 'plc_login.php'; // Get session and API handles require_once 'plc_session.php'; global $plc, $api; // Common functions require_once 'plc_functions.php'; require_once 'plc_sorts.php'; // NOTE: this function exits() after it completes its job, // simply returning leads to html decorations being added around the contents function deliver_and_unlink ($filename) { // for security reasons we want to be able to unlink the resulting file once downloaded // so simply redirecting through a header("Location:") is not good enough $size= filesize($filename); // headers header ("Content-Type: application/octet-stream"); header ("Content-Transfer-Encoding: binary"); header ("Content-Disposition: attachment; filename=" . basename($filename) ); header ("Content-Length: " . $size ); // for getting IE to work properly // from princeton cvs new_plc_www/planetlab/nodes/downloadconf.php 1.2->1.3 header ("Pragma: hack"); header ("Cache-Control: public, must-revalidate"); // outputs the whole file contents print (file_get_contents($filename)); // unlink the file if (! unlink ($filename) ) { // cannot unlink, but how can we notify this ? // certainly not by printing } exit(); } function show_download_confirm_button ($api, $node_id, $action, $can_gen_config, $show_details) { if( $can_gen_config ) { if ($show_details) { $preview=$api->GetBootMedium($node_id,"node-preview",""); print ("

Current node configuration contents

"); print ("
\n$preview
\n"); print ("
"); } $action_labels = array ('download-node-floppy' => 'textual node config (for floppy)' , 'download-node-iso' => 'ISO image', 'download-node-usb' => 'USB image' ); $format = $action_labels [ $action ] ; print( "

\n"); print ("\n"); print ("\n"); print ("\n"); print( "\n" ); print( "
\n" ); } else { echo "

Configuration file cannot be created until missing values above are updated."; } } // check arguments if (empty($_POST['node_id'])) { plc_redirect (l_nodes()); } else { $node_id = intval($_POST['node_id']); } $action=$_POST['action']; switch ($action) { // ACTION: prompt-update // from former node_update.php case "prompt-update": require_once('plc_drupal.php'); $node_info= $api->GetNodes( array( $node_id ), array( "hostname", "model" ) ); drupal_set_title("Updating " . $node_info[0]['hostname']); include 'plc_header.php'; // start form echo "

\n"; echo "\n"; echo "\n"; if( $_POST['error'] ) plc_error(unserialize( $_POST['error'])); echo "

\n \n \n
Hostname:
Model:
\n

\n

\n"; echo "

Back to Node\n"; break; // ACTION: update // from former node_actions.php case "update": $hostname= $_POST['hostname']; $model= $_POST['model']; $fields= array( "hostname"=>$hostname, "model"=>$model ); $api->UpdateNode( intval( $node_id ), $fields ); $error= $api->error(); if( empty( $error ) ) { plc_redirect(l_node($node_id)); } else { echo "". $error . "\n" ; echo "

Press back to retry

"; } break; // ACTION: delete // from former node_actions.php case "delete": $api->DeleteNode( intval( $node_id ) ); plc_redirect(l_nodes()); break; // ACTION: boot-state // from former node_actions.php case "boot-state": switch( $_POST['boot_state'] ) { case 'boot': case 'dbg': case 'inst': case 'rins': case 'rcnf': case 'new': $api->UpdateNode( intval( $node_id ), array( "boot_state" => $_POST['boot_state'] ) ); plc_redirect (l_node($node_id)); break; default: print "
no such boot state " . $_POST['boot_state'] . "
"; break; } break; // ACTION: download-generic case "download-generic-iso": case "download-generic-usb": if ($action=="download-generic-iso") { $boot_action="generic-iso"; } else { $boot_action="generic-usb"; } // place the result in a random-named sub dir for clear filenames $filename = $api->GetBootMedium ($node_id, $boot_action, "%d/%n-%p-%a-%v%s"); $error=$api->error(); // NOTE. for some reason, GetBootMedium sometimes does not report an error but the // file is not created - this happens e.g. when directory owmer/modes are wrong // in this case we get an empty filename // see /etc/httpd/logs/error_log in this case if (empty($error) && empty($filename)) { $error="Unexpected error from GetBootMedium - probably wrong directory modes"; } if (! empty($error)) { print ("
$error
\n"); print ("

Back to node \n"); return ; } else { deliver_and_unlink ($filename); exit(); } break; // ACTION: download-node // from former downloadconf.php case "download-node-floppy": case "download-node-iso": case "download-node-usb": $return= $api->GetNodes( array( $node_id ) ); $node_detail= $return[0]; // non-admin people need to be affiliated with the right site if( ! plc_is_admin() ) { $node_site_id = $node_detail['site_id']; $in_site = plc_in_site($node_site_id); if( ! $in_site) { $error= "Insufficient permission. You cannot create configuration files for this node."; } } $hostname= $node_detail['hostname']; $return= $api->GetInterfaces( array( "node_id" => $node_id ), NULL ); $can_gen_config= 1; $has_primary= 0; if( count($return) > 0 ) { foreach( $return as $interface_detail ) { if( $interface_detail['is_primary'] == true ) { $has_primary= 1; break; } } } if( !$has_primary ) { $can_gen_config= 0; } else { if( $node_detail['hostname'] == "" ) { $can_gen_config= 0; $node_detail['hostname']= "Missing"; } $fields= array("method","ip"); foreach( $fields as $field ) { if( $interface_detail[$field] == "" ) { $can_gen_config= 0; $interface_detail[$field]= "Missing"; } } if( $interface_detail['method'] == "static" ) { $fields= array("gateway","netmask","network","broadcast","dns1"); foreach( $fields as $field ) { if( $interface_detail[$field] == "" ) { $can_gen_config= 0; $interface_detail[$field]= "Missing"; } } } if( $interface_detail['method'] != "static" && $interface_detail['method'] != "dhcp" ) { $can_gen_config= 0; $interface_detail['method']= "Unknown method"; } } $download= $_POST['download']; if( $can_gen_config && !empty($download) ) { switch ($action) { case 'download-node-floppy': $boot_action='node-floppy'; $location = "%d/%n-%v-rename-into-plnode%s"; break; case 'download-node-iso': $boot_action='node-iso'; $location = "%d/%n-%a-%v%s"; break; case 'download-node-usb': $boot_action='node-usb'; $location = "%d/%n-%a-%v%s"; break; } $filename=$api->GetBootMedium($node_id,$boot_action,$location); $error=$api->error(); if (empty($error) && empty($filename)) { $error="Unexpected error from GetBootMedium - probably wrong directory modes"; } if (! empty($error)) { print ("

$error
\n"); print ("

Back to node \n"); return ; } else { deliver_and_unlink ($filename); exit(); } } drupal_set_title("Download boot material for $hostname"); $header= <<In order to create a configuration file for this node using this page, all the interface settings must be up to date. Below is summary of these values. Any missing values must be entered before this can be used. EOF; echo $header; show_download_confirm_button($api, $node_id, $action, $can_gen_config, false); print ("

"); print ("

Current interface settings

\n"); if( $has_primary ) { print( "\n" ); print( "" ); print( "" ); print( "\n" ); print( "" ); print( "\n" ); $nn_id = $interface_detail['interface_id']; print( "" ); print( "" ); print( "\n" ); print( "" ); print( "\n" ); if( $interface_detail['method'] == "static" ) { print( "" ); print( "\n" ); print( "" ); print( "\n" ); print( "" ); print( "\n" ); print( "" ); print( "\n" ); print( "" ); print( "\n" ); print( "" ); if( $interface_detail['dns2'] == "" ) { print( "\n" ); } else { print( "\n" ); } } print ("\n"); $nn_id = $interface_detail['interface_id']; $settings=$api->GetInterfaceTags(array("interface_id" => array($nn_id))); foreach ($settings as $setting) { $category=$setting['category']; $name=$setting['tagname']; $value=$setting['value']; print (" \n"); } print( "
Node Details
node_id:$node_id
Hostname:" . $node_detail['hostname'] . "
Interface Details
Method:" . $interface_detail['method'] . "
IP:" . $interface_detail['ip'] . "
Gateway:" . $interface_detail['gateway'] . "
Network mask:" . $interface_detail['netmask'] . "
Network address:" . $interface_detail['network'] . "
Broadcast address:" . $interface_detail['broadcast'] . "
DNS 1:" . $interface_detail['dns1'] . "
DNS 2:Optional, missing
" . $interface_detail['dns2'] . "
Additional Settings
$category $name $value
\n" ); } else { print( "

This node has no configured primary interface.

\n" ); } show_download_confirm_button($api, $node_id, $action, $can_gen_config, true); break; default: echo "Unkown action <$action>."; plc_redirect (l_node($node_id)); break; } ?>