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