3 // $Id: node_actions.php 1184 2008-02-12 20:33:35Z thierry $
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';
75 $_person= $plc->person;
76 $_roles= $_person['role_ids'];
78 // NOTE: this function exits() after it completes its job,
79 // simply returning leads to html decorations being added around the contents
80 function deliver_and_unlink ($filename) {
82 // for security reasons we want to be able to unlink the resulting file once downloaded
83 // so simply redirecting through a header("Location:") is not good enough
85 $size= filesize($filename);
88 header ("Content-Type: application/octet-stream");
89 header ("Content-Transfer-Encoding: binary");
90 header ("Content-Disposition: attachment; filename=" . basename($filename) );
91 header ("Content-Length: " . $size );
92 // for getting IE to work properly
93 // from princeton cvs new_plc_www/planetlab/nodes/downloadconf.php 1.2->1.3
94 header ("Pragma: hack");
95 header ("Cache-Control: public, must-revalidate");
97 // outputs the whole file contents
98 print (file_get_contents($filename));
101 if (! unlink ($filename) ) {
102 // cannot unlink, but how can we notify this ?
103 // certainly not by printing
108 function show_download_confirm_button($api, $node_id, $action, $can_gen_config, $show_details) {
110 if( $can_gen_config ) {
112 $preview=$api->GetBootMedium($node_id,"node-preview","");
113 print ("<hr /> <h3>Current node configuration contents</h3>");
114 print ("<pre>\n$preview</pre>\n");
117 $action_labels = array ('download-node-floppy' => 'textual node config (for floppy)' ,
118 'download-node-iso' => 'ISO image',
119 'download-node-usb' => 'USB image' );
121 $format = $action_labels [ $action ] ;
122 print( "<p><form method='post' action='node_actions.php'>\n");
123 print ("<input type='hidden' name='node_id' value='$node_id'>\n");
124 print ("<input type='hidden' name='action' value='$action'>\n");
125 print ("<input type='hidden' name='download' value='1'>\n");
126 print( "<input type='submit' value='Download $format'>\n" );
127 print( "</form>\n" );
129 echo "<p><font color=red>Configuration file cannot be created until missing values above are updated.</font>";
135 if (empty($_POST['node_id'])) {
136 header ('location:index.php');
139 $node_id = intval($_POST['node_id']);
142 $action=$_POST['action'];
146 // ACTION: prompt-update
147 // from former node_update.php
148 case "prompt-update":
150 require_once('plc_drupal.php');
151 $node_info= $api->GetNodes( array( $node_id ), array( "hostname", "model" ) );
152 drupal_set_title("Updating " . $node_info[0]['hostname']);
153 include 'plc_header.php';
156 echo "<form method=post action='node_actions.php'>\n";
157 echo "<input type=hidden name='node_id' value='$node_id'></input>\n";
158 echo "<input type=hidden name='action' value='update'></input>\n";
159 if( $_POST['error'] ) echo "<font color=red>". unserialize( $_POST['error'] ."</font>\n" );
160 echo "<p><table cellpadding=2><tbody>\n
161 <tr><th>Hostname: </th><td> <input type=text size=35 name='hostname' value='". $node_info[0]['hostname'] ."'></td></tr>\n
162 <tr><th>Model: </th><td> <input type=text size=35 name='model' value='". $node_info[0]['model'] ."'></td></tr>\n
164 <p><input type=submit value='Update Node'>\n
167 echo "<p><a href='index.php?id=$node_id'>Back to Node</a>\n";
172 // from former node_actions.php
175 $hostname= $_POST['hostname'];
176 $model= $_POST['model'];
178 $fields= array( "hostname"=>$hostname, "model"=>$model );
179 $api->UpdateNode( intval( $node_id ), $fields );
180 $error= $api->error();
182 if( empty( $error ) ) {
183 header( "location: index.php?id=$node_id" );
186 echo "<font color=red>". $error . "</font>\n" ;
187 echo "<p> Press back to retry</p>";
193 // from former node_actions.php
195 $api->DeleteNode( intval( $node_id ) );
196 header( "location: index.php" );
200 // ACTION: boot-state
201 // from former node_actions.php
203 switch( $_POST['boot_state'] ) {
210 $api->UpdateNode( intval( $node_id ), array( "boot_state" => $_POST['boot_state'] ) );
211 header( "location: index.php?id=$node_id" );
215 print "<div class='plc-error'> no such boot state " . $_POST['boot_state'] . "</div>";
220 // ACTION: download-generic
221 case "download-generic-iso":
222 case "download-generic-usb":
224 if ($action=="download-generic-iso") {
225 $boot_action="generic-iso";
227 $boot_action="generic-usb";
230 // place the result in a random-named sub dir for clear filenames
231 $filename = $api->GetBootMedium ($node_id, $boot_action, "%d/%n-%p-%a-%v%s");
232 $error=$api->error();
233 // NOTE. for some reason, GetBootMedium sometimes does not report an error but the
234 // file is not created - this happens e.g. when directory owmer/modes are wrong
235 // in this case we get an empty filename
236 // see /etc/httpd/logs/error_log in this case
237 if (empty($error) && empty($filename)) {
238 $error="Unexpected error from GetBootMedium - probably wrong directory modes";
240 if (! empty($error)) {
241 print ("<div class='plc-error'> $error </div>\n");
242 print ("<p><a href='/db/nodes/index.php?id=$node_id'>Back to node </a>\n");
245 deliver_and_unlink ($filename);
250 // ACTION: download-node
251 // from former downloadconf.php
253 case "download-node-floppy":
254 case "download-node-iso":
255 case "download-node-usb":
257 $return= $api->GetNodes( array( $node_id ) );
258 $node_detail= $return[0];
260 // non-admin people need to be affiliated with the right site
261 if( !in_array( 10, $_roles ) ) {
262 $node_site_id = $node_detail['site_id'];
263 $in_site = in_array ($node_site_id,$_person['site_ids']);
265 $error= "Insufficient permission. You cannot create configuration files for this node.";
269 $hostname= $node_detail['hostname'];
270 $return= $api->GetInterfaces( array( "node_id" => $node_id ), NULL );
275 if( count($return) > 0 ) {
276 foreach( $return as $interface_detail ) {
277 if( $interface_detail['is_primary'] == true ) {
284 if( !$has_primary ) {
287 if( $node_detail['hostname'] == "" ) {
289 $node_detail['hostname']= "<i>Missing</i>";
292 $fields= array("method","ip");
293 foreach( $fields as $field ) {
294 if( $interface_detail[$field] == "" ) {
296 $interface_detail[$field]= "<i>Missing</i>";
300 if( $interface_detail['method'] == "static" ) {
301 $fields= array("gateway","netmask","network","broadcast","dns1");
302 foreach( $fields as $field ) {
303 if( $interface_detail[$field] == "" ) {
305 $interface_detail[$field]= "<i>Missing</i>";
310 if( $interface_detail['method'] != "static"
311 && $interface_detail['method'] != "dhcp" ) {
313 $interface_detail['method']= "<i>Unknown method</i>";
317 $download= $_POST['download'];
319 if( $can_gen_config && !empty($download) ) {
321 case 'download-node-floppy':
322 $boot_action='node-floppy';
323 $location = "%d/%n-%v-rename-into-plnode%s";
325 case 'download-node-iso':
326 $boot_action='node-iso';
327 $location = "%d/%n-%a-%v%s";
329 case 'download-node-usb':
330 $boot_action='node-usb';
331 $location = "%d/%n-%a-%v%s";
335 $filename=$api->GetBootMedium($node_id,$boot_action,$location);
336 $error=$api->error();
337 if (empty($error) && empty($filename)) {
338 $error="Unexpected error from GetBootMedium - probably wrong directory modes";
340 if (! empty($error)) {
341 print ("<div class='plc-error'> $error </div>\n");
342 print ("<p><a href='/db/nodes/index.php?id=$node_id'>Back to node </a>\n");
345 deliver_and_unlink ($filename);
350 drupal_set_title("Download boot material for $hostname");
354 WARNING: Creating a new configuration file for this node will generate
355 a new node key, and any existing configuration file will be unusable and
356 must be updated before the node can successfully boot, install, or
359 <p>In order to create a configuration file for this node using this page,
360 all the node network settings must be up to date. Below is summary of these
361 values. Any missing values must be entered before this can be used.
367 show_download_confirm_button($api, $node_id, $action, $can_gen_config, false);
369 print ("<h3>Current node network settings</h3>\n");
372 print( "<table border=\"0\" cellspacing=\"4\">\n" );
374 print( "<tr><th colspan=2><a href='index.php?id=$node_id'>Node Details</a></th></tr>" );
375 print( "<tr><th>node_id:</th>" );
376 print( "<td>$node_id</td></tr>\n" );
377 print( "<tr><th>Hostname:</th>" );
378 print( "<td>" . $node_detail['hostname'] . "</td></tr>\n" );
380 $nn_id = $interface_detail['interface_id'];
381 print( "<tr><th colspan=2><a href='interfaces.php?id=$nn_id'>Node Network Details</a></th></tr>" );
383 print( "<tr><th>Method:</th>" );
384 print( "<td>" . $interface_detail['method'] . "</td></tr>\n" );
385 print( "<tr><th>IP:</th>" );
386 print( "<td>" . $interface_detail['ip'] . "</td></tr>\n" );
388 if( $interface_detail['method'] == "static" ) {
389 print( "<tr><th>Gateway:</th>" );
390 print( "<td>" . $interface_detail['gateway'] . "</td></tr>\n" );
391 print( "<tr><th>Network mask:</th>" );
392 print( "<td>" . $interface_detail['netmask'] . "</td></tr>\n" );
393 print( "<tr><th>Network address:</th>" );
394 print( "<td>" . $interface_detail['network'] . "</td></tr>\n" );
395 print( "<tr><th>Broadcast address:</th>" );
396 print( "<td>" . $interface_detail['broadcast'] . "</td></tr>\n" );
397 print( "<tr><th>DNS 1:</th>" );
398 print( "<td>" . $interface_detail['dns1'] . "</td></tr>\n" );
399 print( "<tr><th>DNS 2:</th>" );
400 if( $interface_detail['dns2'] == "" ) {
401 print( "<td><i>Optional, missing</i></td></tr>\n" );
403 print( "<td>" . $interface_detail['dns2'] . "</td></tr>\n" );
407 print ("<tr><th colspan=2><a href='interfaces.php?id=$nn_id'>Additional Settings</a></th></tr>\n");
408 $nn_id = $interface_detail['interface_id'];
409 $settings=$api->GetInterfaceTags(array("interface_id" => array($nn_id)));
410 foreach ($settings as $setting) {
411 $category=$setting['category'];
412 $name=$setting['name'];
413 $value=$setting['value'];
414 print (" <tr><th> $category $name </th><td> $value </td></tr>\n");
417 print( "</table>\n" );
419 print( "<p class='plc-warning'>This node has no configured primary network.</p>\n" );
422 show_download_confirm_button($api, $node_id, $action, $can_gen_config, true);
426 echo "Unkown action <$action>.";
427 header("location:index.php?id=" . $node_id);