4 // This file was created when we decided to make the node page consistent with the other pages
5 // That is to say, we wanted the 'Update' and 'Delete' functions to appear in a drop-down
6 // menu like for the other objects
7 // It appeared after analysis that it was easier to have the following
8 // functions gathered in a single php file
11 // displays current settings and prompt for changes before going to node_actions.php
12 // (*) node_actions.php
13 // (GET) 'del=node_id'
14 // (GET) 'update=node_id' -> actual UpdateNode
15 // (POST) node_id=node_id ng_add=nodegroup_id
17 // (POST) boot_state=boot_state node_id=node_id
18 // (POST) ng_add=nodegroup_id
19 // (*) downloadconf.php
20 // (GET) id=node_id [download=1]
21 // either showed current status, or performed actual config download
23 // in this new version we support only POST behaviour with the following interface
24 // REQUIRED : node_id=node_id
25 // (*) action='prompt-update' : former node_update.php
26 // (*) action='update'
28 // model= : actually updated the node
29 // (*) action='boot-state'
30 // boot_state= : changes bootstate
31 // (*) action='delete' : deletes node
32 // (*) action='download-node-floppy' :
33 // (*) action='download-node-iso' :
34 // (*) action='download-node-usb' :
35 // : same as former downloadconf.php with download unset
36 // if in addition POST contains a non-empty field 'download' :
37 // : performs actual node-dep download
38 // (*) action='download-generic-iso':
39 // (*) action='download-generic-usb':
40 // : performs actual generic download
41 // (*) action='add-in-nodegroup': should include this for compatibility, replaces ng_add,
42 // though I could not figure where it's called
45 // TODO : manage a post field for displaying results of previous page
46 // see the special 'flash' in rails
48 // delivering node-dependant images requires larger memory limit
49 // trial and error, based on the current sizes
50 // generic-ISO 43980800
51 // generic-usb 44720128
58 // Bottom line is, looks like we need in the order of twice the file size
59 // so let's play it safe
60 // Thierry - for 4.2, we need a larger area, was 100 for 4.1
61 ini_set("memory_limit","150M");
64 require_once 'plc_login.php';
66 // Get session and API handles
67 require_once 'plc_session.php';
71 require_once 'plc_functions.php';
72 require_once 'plc_sorts.php';
74 // NOTE: this function exits() after it completes its job,
75 // simply returning leads to html decorations being added around the contents
76 function deliver_and_unlink ($filename) {
78 // for security reasons we want to be able to unlink the resulting file once downloaded
79 // so simply redirecting through a header("Location:") is not good enough
81 $size= filesize($filename);
84 header ("Content-Type: application/octet-stream");
85 header ("Content-Transfer-Encoding: binary");
86 header ("Content-Disposition: attachment; filename=" . basename($filename) );
87 header ("Content-Length: " . $size );
88 // for getting IE to work properly
89 // from princeton cvs new_plc_www/planetlab/nodes/downloadconf.php 1.2->1.3
90 header ("Pragma: hack");
91 header ("Cache-Control: public, must-revalidate");
93 // outputs the whole file contents
94 print (file_get_contents($filename));
97 if (! unlink ($filename) ) {
98 // cannot unlink, but how can we notify this ?
99 // certainly not by printing
104 function show_download_confirm_button ($api, $node_id, $action, $can_gen_config, $show_details) {
106 if( $can_gen_config ) {
108 $preview=$api->GetBootMedium($node_id,"node-preview","");
109 print ("<hr /> <h3>Current node configuration contents</h3>");
110 print ("<pre>\n$preview</pre>\n");
113 $action_labels = array ('download-node-floppy' => 'textual node config (for floppy)' ,
114 'download-node-iso' => 'ISO image',
115 'download-node-usb' => 'USB image' );
117 $format = $action_labels [ $action ] ;
118 print( "<p><form method='post' action='node_actions.php'>\n");
119 print ("<input type='hidden' name='node_id' value='$node_id'>\n");
120 print ("<input type='hidden' name='action' value='$action'>\n");
121 print ("<input type='hidden' name='download' value='1'>\n");
122 print( "<input type='submit' value='Download $format'>\n" );
123 print( "</form>\n" );
125 echo "<p><font color=red>Configuration file cannot be created until missing values above are updated.</font>";
131 if (empty($_POST['node_id'])) {
132 header ('location:index.php');
135 $node_id = intval($_POST['node_id']);
138 $action=$_POST['action'];
142 // ACTION: prompt-update
143 // from former node_update.php
144 case "prompt-update":
146 require_once('plc_drupal.php');
147 $node_info= $api->GetNodes( array( $node_id ), array( "hostname", "model" ) );
148 drupal_set_title("Updating " . $node_info[0]['hostname']);
149 include 'plc_header.php';
152 echo "<form method=post action='node_actions.php'>\n";
153 echo "<input type=hidden name='node_id' value='$node_id'></input>\n";
154 echo "<input type=hidden name='action' value='update'></input>\n";
155 if( $_POST['error'] ) plc_error(unserialize( $_POST['error']));
156 echo "<p><table cellpadding=2><tbody>\n
157 <tr><th>Hostname: </th><td> <input type=text size=35 name='hostname' value='". $node_info[0]['hostname'] ."'></td></tr>\n
158 <tr><th>Model: </th><td> <input type=text size=35 name='model' value='". $node_info[0]['model'] ."'></td></tr>\n
160 <p><input type=submit value='Update Node'>\n
163 echo "<p><a href='index.php?id=$node_id'>Back to Node</a>\n";
168 // from former node_actions.php
171 $hostname= $_POST['hostname'];
172 $model= $_POST['model'];
174 $fields= array( "hostname"=>$hostname, "model"=>$model );
175 $api->UpdateNode( intval( $node_id ), $fields );
176 $error= $api->error();
178 if( empty( $error ) ) {
179 header( "location: index.php?id=$node_id" );
182 echo "<font color=red>". $error . "</font>\n" ;
183 echo "<p> Press back to retry</p>";
189 // from former node_actions.php
191 $api->DeleteNode( intval( $node_id ) );
192 header( "location: index.php" );
196 // ACTION: boot-state
197 // from former node_actions.php
199 switch( $_POST['boot_state'] ) {
206 $api->UpdateNode( intval( $node_id ), array( "boot_state" => $_POST['boot_state'] ) );
207 header( "location: index.php?id=$node_id" );
211 print "<div class='plc-error'> no such boot state " . $_POST['boot_state'] . "</div>";
216 // ACTION: download-generic
217 case "download-generic-iso":
218 case "download-generic-usb":
220 if ($action=="download-generic-iso") {
221 $boot_action="generic-iso";
223 $boot_action="generic-usb";
226 // place the result in a random-named sub dir for clear filenames
227 $filename = $api->GetBootMedium ($node_id, $boot_action, "%d/%n-%p-%a-%v%s");
228 $error=$api->error();
229 // NOTE. for some reason, GetBootMedium sometimes does not report an error but the
230 // file is not created - this happens e.g. when directory owmer/modes are wrong
231 // in this case we get an empty filename
232 // see /etc/httpd/logs/error_log in this case
233 if (empty($error) && empty($filename)) {
234 $error="Unexpected error from GetBootMedium - probably wrong directory modes";
236 if (! empty($error)) {
237 print ("<div class='plc-error'> $error </div>\n");
238 print ("<p><a href='/db/nodes/index.php?id=$node_id'>Back to node </a>\n");
241 deliver_and_unlink ($filename);
246 // ACTION: download-node
247 // from former downloadconf.php
249 case "download-node-floppy":
250 case "download-node-iso":
251 case "download-node-usb":
253 $return= $api->GetNodes( array( $node_id ) );
254 $node_detail= $return[0];
256 // non-admin people need to be affiliated with the right site
257 if( ! plc_is_admin() ) {
258 $node_site_id = $node_detail['site_id'];
259 $in_site = plc_in_site($node_site_id);
261 $error= "Insufficient permission. You cannot create configuration files for this node.";
265 $hostname= $node_detail['hostname'];
266 $return= $api->GetInterfaces( array( "node_id" => $node_id ), NULL );
271 if( count($return) > 0 ) {
272 foreach( $return as $interface_detail ) {
273 if( $interface_detail['is_primary'] == true ) {
280 if( !$has_primary ) {
283 if( $node_detail['hostname'] == "" ) {
285 $node_detail['hostname']= "<i>Missing</i>";
288 $fields= array("method","ip");
289 foreach( $fields as $field ) {
290 if( $interface_detail[$field] == "" ) {
292 $interface_detail[$field]= "<i>Missing</i>";
296 if( $interface_detail['method'] == "static" ) {
297 $fields= array("gateway","netmask","network","broadcast","dns1");
298 foreach( $fields as $field ) {
299 if( $interface_detail[$field] == "" ) {
301 $interface_detail[$field]= "<i>Missing</i>";
306 if( $interface_detail['method'] != "static"
307 && $interface_detail['method'] != "dhcp" ) {
309 $interface_detail['method']= "<i>Unknown method</i>";
313 $download= $_POST['download'];
315 if( $can_gen_config && !empty($download) ) {
317 case 'download-node-floppy':
318 $boot_action='node-floppy';
319 $location = "%d/%n-%v-rename-into-plnode%s";
321 case 'download-node-iso':
322 $boot_action='node-iso';
323 $location = "%d/%n-%a-%v%s";
325 case 'download-node-usb':
326 $boot_action='node-usb';
327 $location = "%d/%n-%a-%v%s";
331 $filename=$api->GetBootMedium($node_id,$boot_action,$location);
332 $error=$api->error();
333 if (empty($error) && empty($filename)) {
334 $error="Unexpected error from GetBootMedium - probably wrong directory modes";
336 if (! empty($error)) {
337 print ("<div class='plc-error'> $error </div>\n");
338 print ("<p><a href='/db/nodes/index.php?id=$node_id'>Back to node </a>\n");
341 deliver_and_unlink ($filename);
346 drupal_set_title("Download boot material for $hostname");
350 WARNING: Creating a new configuration file for this node will generate
351 a new node key, and any existing configuration file will be unusable and
352 must be updated before the node can successfully boot, install, or
355 <p>In order to create a configuration file for this node using this page,
356 all the interface settings must be up to date. Below is summary of these
357 values. Any missing values must be entered before this can be used.
363 show_download_confirm_button($api, $node_id, $action, $can_gen_config, false);
365 print ("<h3>Current interface settings</h3>\n");
368 print( "<table border=\"0\" cellspacing=\"4\">\n" );
370 print( "<tr><th colspan=2><a href='index.php?id=$node_id'>Node Details</a></th></tr>" );
371 print( "<tr><th>node_id:</th>" );
372 print( "<td>$node_id</td></tr>\n" );
373 print( "<tr><th>Hostname:</th>" );
374 print( "<td>" . $node_detail['hostname'] . "</td></tr>\n" );
376 $nn_id = $interface_detail['interface_id'];
377 print( "<tr><th colspan=2><a href='interfaces.php?id=$nn_id'>Interface Details</a></th></tr>" );
379 print( "<tr><th>Method:</th>" );
380 print( "<td>" . $interface_detail['method'] . "</td></tr>\n" );
381 print( "<tr><th>IP:</th>" );
382 print( "<td>" . $interface_detail['ip'] . "</td></tr>\n" );
384 if( $interface_detail['method'] == "static" ) {
385 print( "<tr><th>Gateway:</th>" );
386 print( "<td>" . $interface_detail['gateway'] . "</td></tr>\n" );
387 print( "<tr><th>Network mask:</th>" );
388 print( "<td>" . $interface_detail['netmask'] . "</td></tr>\n" );
389 print( "<tr><th>Network address:</th>" );
390 print( "<td>" . $interface_detail['network'] . "</td></tr>\n" );
391 print( "<tr><th>Broadcast address:</th>" );
392 print( "<td>" . $interface_detail['broadcast'] . "</td></tr>\n" );
393 print( "<tr><th>DNS 1:</th>" );
394 print( "<td>" . $interface_detail['dns1'] . "</td></tr>\n" );
395 print( "<tr><th>DNS 2:</th>" );
396 if( $interface_detail['dns2'] == "" ) {
397 print( "<td><i>Optional, missing</i></td></tr>\n" );
399 print( "<td>" . $interface_detail['dns2'] . "</td></tr>\n" );
403 print ("<tr><th colspan=2><a href='interfaces.php?id=$nn_id'>Additional Settings</a></th></tr>\n");
404 $nn_id = $interface_detail['interface_id'];
405 $settings=$api->GetInterfaceTags(array("interface_id" => array($nn_id)));
406 foreach ($settings as $setting) {
407 $category=$setting['category'];
408 $name=$setting['tagname'];
409 $value=$setting['value'];
410 print (" <tr><th> $category $name </th><td> $value </td></tr>\n");
413 print( "</table>\n" );
415 print( "<p class='plc-warning'>This node has no configured primary interface.</p>\n" );
418 show_download_confirm_button($api, $node_id, $action, $can_gen_config, true);
422 echo "Unkown action <$action>.";
423 header("location:index.php?id=" . $node_id);