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