update
[plewww.git] / planetlab / nodes / node_downloads.php
1 <?php
2
3   // $Id$
4
5   // cleaned up, keep only the actions related to downloading stuff
6   // REQUIRED : node_id=node_id
7   // (*) action='download-node-floppy' : 
8   // (*) action='download-node-iso' : 
9   // (*) action='download-node-usb' : 
10   //                            : same as former downloadconf.php with download unset
11   //     if in addition POST contains a non-empty field 'download' :
12   //                            : performs actual node-dep download
13   // (*) action='download-generic-iso':
14   // (*) action='download-generic-usb':
15   //                            : performs actual generic download
16
17 // delivering node-dependant images requires larger memory limit
18 // trial and error, based on the current sizes
19 // generic-ISO 43980800 
20 // generic-usb 44720128 
21 // 256M OK
22 // 128M OK
23 // 96M OK
24 // 88M KO
25 // 80M KO
26 // 64M KO
27 // Bottom line is, looks like we need in the order of twice the file size
28 // so let's play it safe
29 // Thierry - for 4.2, we need a larger area, was 100 for 4.1
30 ini_set("memory_limit","150M");
31
32 // Require login
33 require_once 'plc_login.php';
34
35 // Get session and API handles
36 require_once 'plc_session.php';
37 global $plc, $api;
38
39 // Common functions
40 require_once 'plc_functions.php';
41 require_once 'plc_sorts.php';
42
43 // NOTE: this function exits() after it completes its job, 
44 // simply returning leads to html decorations being added around the contents
45 function deliver_and_unlink ($filename) {
46   
47   // for security reasons we want to be able to unlink the resulting file once downloaded
48   // so simply redirecting through a header("Location:") is not good enough
49
50   $size= filesize($filename);
51
52   // headers
53   header ("Content-Type: application/octet-stream");
54   header ("Content-Transfer-Encoding: binary");
55   header ("Content-Disposition: attachment; filename=" . basename($filename) );
56   header ("Content-Length: " . $size );
57   // for getting IE to work properly
58   // from princeton cvs new_plc_www/planetlab/nodes/downloadconf.php 1.2->1.3
59   header ("Pragma: hack");
60   header ("Cache-Control: public, must-revalidate");
61
62   // outputs the whole file contents
63   print (file_get_contents($filename));
64   
65   // unlink the file
66   if (! unlink ($filename) ) {
67     // cannot unlink, but how can we notify this ?
68     // certainly not by printing
69   }
70   exit();
71 }
72
73 function show_download_confirm_button ($api, $node_id, $action, $can_gen_config, $show_details) {
74
75   if( $can_gen_config ) {
76     if ($show_details) {
77       $preview=$api->GetBootMedium($node_id,"node-preview","");
78       print ("<hr /> <h3>Current node configuration contents</h3>");
79       print ("<pre>\n$preview</pre>\n");
80       print ("<hr />");
81     }
82     $action_labels = array ('download-node-floppy' => 'textual node config (for floppy)' ,
83                             'download-node-iso' => 'ISO image',
84                             'download-node-usb' => 'USB image' );
85     
86     $format = $action_labels [ $action ] ;
87     print( "<p><form method='post' action='node_downloads.php'>\n");
88     print ("<input type='hidden' name='node_id' value='$node_id'>\n");
89     print ("<input type='hidden' name='action' value='$action'>\n");
90     print ("<input type='hidden' name='download' value='1'>\n");
91     print( "<input type='submit' value='Download $format'>\n" );
92     print( "</form>\n" );
93   } else {
94     echo "<p><font color=red>Configuration file cannot be created until missing values above are updated.</font>";
95   }
96 }
97
98 // check arguments
99
100 if (empty($_POST['node_id'])) {
101   plc_redirect (l_nodes());
102  } else {
103   $node_id = intval($_POST['node_id']);
104 }
105
106 $action=$_POST['action'];
107
108 switch ($action) {
109
110  case "download-generic-iso":
111  case "download-generic-usb":
112    
113    if ($action=="download-generic-iso") {
114      $boot_action="generic-iso";
115    } else {
116      $boot_action="generic-usb";
117    }
118
119    // place the result in a random-named sub dir for clear filenames
120    $filename = $api->GetBootMedium ($node_id, $boot_action, "%d/%n-%p-%a-%v%s");
121    $error=$api->error();
122    // NOTE. for some reason, GetBootMedium sometimes does not report an error but the
123    // file is not created - this happens e.g. when directory owmer/modes are wrong 
124    // in this case we get an empty filename
125    // see /etc/httpd/logs/error_log in this case
126    if (empty($error) && empty($filename)) {
127      $error="Unexpected error from GetBootMedium - probably wrong directory modes";
128    }    
129    if (! empty($error)) {
130      print ("<div class='plc-error'> $error </div>\n");
131      print ("<p><a href='/db/nodes/index.php?id=$node_id'>Back to node </a>\n");
132      return ;
133    } else {
134      deliver_and_unlink ($filename);
135      exit();
136    }
137    break;
138
139    // ACTION: download-node
140    // from former downloadconf.php
141    
142  case "download-node-floppy":
143  case "download-node-iso":
144  case "download-node-usb":
145    
146    $return= $api->GetNodes( array( $node_id ) );
147    $node_detail= $return[0];
148
149    // non-admin people need to be affiliated with the right site
150    if( ! plc_is_admin() ) {
151      $node_site_id = $node_detail['site_id'];
152      $in_site = plc_in_site($node_site_id);
153      if( ! $in_site) {
154        $error= "Insufficient permission. You cannot create configuration files for this node.";
155      }
156    }
157
158    $hostname= $node_detail['hostname'];
159    $return= $api->GetInterfaces( array( "node_id" => $node_id ), NULL );
160    
161    $can_gen_config= 1;
162    $has_primary= 0;
163    
164    if( count($return) > 0 ) {
165      foreach( $return as $interface_detail ) {
166        if( $interface_detail['is_primary'] == true ) {
167          $has_primary= 1;
168          break;
169        }
170      }
171    }
172
173    if( !$has_primary ) {
174      $can_gen_config= 0;
175    } else {
176      if( $node_detail['hostname'] == "" ) {
177        $can_gen_config= 0;
178        $node_detail['hostname']= "<i>Missing</i>";
179      }
180      
181      $fields= array("method","ip");
182      foreach( $fields as $field ) {
183        if( $interface_detail[$field] == "" ) {
184          $can_gen_config= 0;
185          $interface_detail[$field]= "<i>Missing</i>";
186        }
187      }
188
189      if( $interface_detail['method'] == "static" ) {
190        $fields= array("gateway","netmask","network","broadcast","dns1");
191        foreach( $fields as $field ) {
192          if( $interface_detail[$field] == "" ) {
193            $can_gen_config= 0;
194            $interface_detail[$field]= "<i>Missing</i>";
195          }
196        }
197      }
198
199      if(    $interface_detail['method'] != "static" 
200          && $interface_detail['method'] != "dhcp" ) {
201        $can_gen_config= 0;
202        $interface_detail['method']= "<i>Unknown method</i>";
203      }
204    }
205
206    $download= $_POST['download'];
207    
208    if( $can_gen_config && !empty($download) ) {
209      switch ($action) {
210      case 'download-node-floppy':
211        $boot_action='node-floppy'; 
212        $location = "%d/%n-%v-rename-into-plnode%s";
213        break;
214      case 'download-node-iso':
215        $boot_action='node-iso';
216        $location = "%d/%n-%a-%v%s";
217        break;
218      case 'download-node-usb':
219        $boot_action='node-usb';
220        $location = "%d/%n-%a-%v%s";
221        break;
222      }   
223
224      $filename=$api->GetBootMedium($node_id,$boot_action,$location);
225      $error=$api->error();
226      if (empty($error) && empty($filename)) {
227        $error="Unexpected error from GetBootMedium - probably wrong directory modes";
228      }    
229      if (! empty($error)) {
230        print ("<div class='plc-error'> $error </div>\n");
231        print ("<p><a href='/db/nodes/index.php?id=$node_id'>Back to node </a>\n");
232        return ;
233      } else {
234        deliver_and_unlink ($filename);
235        exit();
236      }
237    }
238
239    drupal_set_title("Download boot material for $hostname");
240
241    $header= <<<EOF
242
243 WARNING: Creating a new configuration file for this node will generate
244 a new node key, and any existing configuration file will be unusable and
245  must be updated before the node can successfully boot, install, or
246 go into debug mode.
247
248 <p>In order to create a configuration file for this node using this page,
249 all the interface settings must be up to date. Below is summary of these
250 values. Any missing values must be entered before this can be used.
251
252 EOF;
253
254    echo $header;
255
256    show_download_confirm_button($api, $node_id, $action, $can_gen_config, false);
257    print ("<p>");
258    print ("<h3>Current interface settings</h3>\n");
259    
260 if( $has_primary ) {
261   print( "<table border=\"0\" cellspacing=\"4\">\n" );
262   
263   print( "<tr><th colspan='2'><a href='index.php?id=$node_id'>Node Details</a></th></tr>" );
264   print( "<tr><th>node_id:</th>" );
265   print( "<td>$node_id</td></tr>\n" );
266   print( "<tr><th>Hostname:</th>" );
267   print( "<td>" . $node_detail['hostname'] . "</td></tr>\n" );
268
269   $nn_id = $interface_detail['interface_id'];
270   print( "<tr><th colspan='2'><a href='interface.php?id=$nn_id'>Interface Details</a></th></tr>" );
271
272   print( "<tr><th>Method:</th>" );
273   print( "<td>" . $interface_detail['method'] . "</td></tr>\n" );
274   print( "<tr><th>IP:</th>" );
275   print( "<td>" . $interface_detail['ip'] . "</td></tr>\n" );
276
277   if( $interface_detail['method'] == "static" ) {
278       print( "<tr><th>Gateway:</th>" );
279       print( "<td>" . $interface_detail['gateway'] . "</td></tr>\n" );
280       print( "<tr><th>Network mask:</th>" );
281       print( "<td>" . $interface_detail['netmask'] . "</td></tr>\n" );
282       print( "<tr><th>Network address:</th>" );
283       print( "<td>" . $interface_detail['network'] . "</td></tr>\n" );
284       print( "<tr><th>Broadcast address:</th>" );
285       print( "<td>" . $interface_detail['broadcast'] . "</td></tr>\n" );
286       print( "<tr><th>DNS 1:</th>" );
287       print( "<td>" . $interface_detail['dns1'] . "</td></tr>\n" );
288       print( "<tr><th>DNS 2:</th>" );
289       if( $interface_detail['dns2'] == "" ) {
290         print( "<td><i>Optional, missing</i></td></tr>\n" );
291       } else {
292         print( "<td>" . $interface_detail['dns2'] . "</td></tr>\n" );
293       }
294     }
295
296   print ("<tr><th colspan='2'><a href='interface.php?id=$nn_id'>Additional Settings</a></th></tr>\n");
297   $nn_id = $interface_detail['interface_id'];
298   $settings=$api->GetInterfaceTags(array("interface_id" => array($nn_id)));
299   foreach ($settings as $setting) {
300     $category=$setting['category'];
301     $name=$setting['tagname'];
302     $value=$setting['value'];
303     print (" <tr><th> $category $name </th><td> $value </td></tr>\n");
304   }
305
306   print( "</table>\n" );
307 } else {
308   print( "<p class='plc-warning'>This node has no configured primary interface.</p>\n" );
309 }
310
311  show_download_confirm_button($api, $node_id, $action, $can_gen_config, true);
312  break;
313  
314  default:
315    drupal-set_error("Unkown action $action in node_downloads.php");
316    plc_redirect (l_node($node_id));
317    break;
318  }
319
320 ?>