395ddce7e4d5f4f90bbb6fb2d43586eb7ece4d65
[plewww.git] / planetlab / nodes / index.php
1 <?php
2
3 // $Id: index.php 1175 2008-02-07 16:20:15Z thierry $
4
5 // Require login
6 require_once 'plc_login.php';
7
8 // Get session and API handles
9 require_once 'plc_session.php';
10 global $plc, $api, $adm;
11
12 // Print header
13 require_once 'plc_drupal.php';
14 drupal_set_title('Nodes');
15 include 'plc_header.php';
16
17 // Common functions
18 require_once 'plc_functions.php';
19 require_once 'plc_sorts.php';
20
21 // find person roles
22 $_person= $plc->person;
23 $_roles= $_person['role_ids'];
24
25 ////////////////////
26 // The set of columns to fetch
27 // and the filter applied for fetching sites
28 $columns = array( "node_id", "hostname", "boot_state", "peer_id" ) ;
29 $filter = array("node_type"=>"regular");
30 if ( in_array( '10', $_roles ) || in_array('20', $_roles) || in_array('40',$_roles)) {
31   // admins, PIs and techs can see interface details
32   $columns [] = "interface_ids";
33  }
34
35 //////////////////
36 // perform post-processing on objects as returned by GetNodes
37 // performs sanity check and summarize the result in a single column
38 // performs in-place replacement, so passes a reference
39 function layout_node ($node) {
40
41   // we need the 'interface_ids' field to do this
42   // so regular users wont run this
43   if ( ! array_key_exists ('interface_ids', $node))
44     return $node;
45     
46   $messages=array();
47   
48   // do all this stuff on local nodes only
49   if ( ! $node['peer_id'] ) {
50     // check that the node has keys
51     if (count($node['interface_ids']) == 0)
52       $messages [] = "No interface";
53     
54   }
55   // but always cleanup $node columns
56   unset ($node['interface_ids']);
57   $node['status'] = plc_make_table('plc-warning',$messages);
58   $node['comon'] = plc_comon_button("node_id",$node['node_id']);
59   return $node;
60 }
61
62 // if nodepattern is set then set id to that node's id.
63 // we use GET rather than POST so paginate can display the right contents on subsequent pages
64 // can be useful for writing bookmarkable URL's as well
65 if( $_GET['nodepattern'] || $_GET['peerscope']) {
66   $nodepattern= $_GET['nodepattern'];
67   if (empty($nodepattern)) { 
68     $nodepattern="*";
69   }
70   $filter = array_merge (array( "hostname"=>$nodepattern ), $filter);
71   switch ($_GET['peerscope']) {
72   case '':
73     $peer_label="all peers";
74     break;
75   case 'local':
76     $filter=array_merge(array("peer_id"=>NULL),$filter);
77     $peer_label="local peer";
78     break;
79   case 'foreign':
80     $filter=array_merge(array("~peer_id"=>NULL),$filter);
81     $peer_label="foreign peers";
82     break;
83   default:
84     $peer_id=intval($_GET['peerscope']);
85     $filter=array_merge(array("peer_id"=>$peer_id),$filter);
86     $peer=$api->GetPeers(array("peer_id"=>$peer_id));
87     $peer_label='peer "' . $peer[0]['peername'] . '"';
88     break;
89   }
90   // need to use a hash filter for patterns to be properly handled
91   $nodes= $api->GetNodes($filter, $columns);
92   $nodes_count = count ($nodes);
93   if ( $nodes_count == 1) {
94     header( "location: index.php?id=". $nodes[0]['node_id'] );
95     exit();
96   } else if ( $nodes_count == 0) {
97     echo "<span class='plc-warning'> No node matching $nodepattern </span>";
98   } else {
99     drupal_set_title ("Nodes matching $nodepattern on". $peer_label);
100     $nodes = array_map(layout_node,$nodes);
101     sort_nodes ($nodes);
102     echo paginate( $nodes, "node_id", "Nodes", 25, "hostname");
103   }
104 }
105 // if a site_id is given, display the site nodes only
106 else if( $_GET['site_id'] ) {
107
108   $site_id= $_GET['site_id'];
109
110   // Get site info
111   $site_info= $api->GetSites( array( intval( $site_id ) ), array( "name", "node_ids" ) );
112   drupal_set_title("Nodes on site " . $site_info[0]['name']);
113
114   // Get site nodes
115   $nodes= $api->GetNodes( array_merge(array('node_id'=>$site_info[0]['node_ids']),$filter), $columns);
116
117   if ( empty ($nodes) ) {
118     echo "No node to display";
119   } else {
120
121     $nodes = array_map(layout_node,$nodes);
122     sort_nodes( $nodes );       
123
124     echo paginate( $nodes, "node_id", "Nodes", 25, "hostname");
125   }
126
127 }
128 // if a slice_id is given, display only the nodes related to this slice
129 else if( $_GET['slice_id'] ) {
130
131   $slice_id= $_GET['slice_id'];
132
133   // Get slice infos
134   $slice_info= $api->GetSlices( array( intval( $slice_id ) ), array( "name", "node_ids" ) );
135   drupal_set_title($slice_info[0]['name']."run on");
136
137   // Get slice nodes
138   $nodes= $api->GetNodes( array_merge(array('node_id'=>$slice_info[0]['node_ids']),$filter), $columns);
139
140   if ( empty ($nodes) ) {
141     echo "No node to display";
142   } else {
143
144     $nodes = array_map(layout_node,$nodes);
145     sort_nodes( $nodes );       
146
147     echo paginate( $nodes, "node_id", "Nodes", 25, "hostname");
148     echo "<br /><p><a href='/db/slices/index.php?id=".$slice_id.">Back to slice page</a></div>";
149   }
150   
151  }
152 // if no node id, display list of nodes to choose
153 elseif( !$_GET['id'] ) {
154
155   // GetNodes API call
156   $nodes= $api->GetNodes( empty($filter) ? NULL : $filter, $columns );
157
158   if ( empty ($nodes) ) {
159     echo "No node to display";
160   } else {
161     
162     $nodes = array_map(layout_node,$nodes);
163     sort_nodes( $nodes );
164
165     drupal_set_html_head('<script type="text/javascript" src="/planetlab/bsn/bsn.Ajax.js"></script>
166     <script type="text/javascript" src="/planetlab/bsn/bsn.DOM.js"></script>
167     <script type="text/javascript" src="/planetlab/bsn/bsn.AutoSuggest.js"></script>');
168
169     echo "<div>\n
170         <form method=get action='index.php'>\n";
171     echo "<table><tr>\n
172 <th><label for='testinput'>Enter hostname or pattern: : </label></th>\n
173 <td><input type='text' id='testinput' name='nodepattern' size=40 value='' /></td>\n
174 <td rowspan=2><input type=submit value='Select Node' /></td>\n
175 </tr> <tr>
176 <th><label for='peerscope'>Federation scope: </label></th>\n
177 <td><select id='peerscope' name='peerscope' onChange='submit()'>\n
178 ";
179     echo plc_peers_option_list($api);
180     echo "</select></td>\n
181          </tr></table></form></div>\n
182           <br />\n";
183
184
185 echo paginate( $nodes, "node_id", "Nodes", 25, "hostname" );
186
187     echo "<script type=\"text/javascript\">\n
188 var options = {\n
189         script:\"/planetlab/nodes/test.php?\",\n
190         varname:\"input\",\n
191         minchars:1\n
192 };\n
193 var as = new AutoSuggest('testinput', options);\n
194 </script>\n";
195   }
196 }
197
198 if ( $_GET['id'] ) {
199   // get the node id from the URL
200   $node_id= intval( $_GET['id'] );
201
202   // make the api call to pull that nodes DATA
203   $node_info= $api->GetNodes( array( $node_id ) );
204
205   if (empty ($node_info)) {
206     echo "No such node.";
207   } else {
208
209     // node info
210     $hostname= $node_info[0]['hostname'];
211     $boot_state= $node_info[0]['boot_state'];
212     $site_id= $node_info[0]['site_id'];
213     $model= $node_info[0]['model'];
214     $version= $node_info[0]['version'];
215
216     // arrays of ids of node info
217     $slice_ids= $node_info[0]['slice_ids'];
218     $conf_file_ids= $node_info[0]['conf_file_ids'];
219     $interface_ids= $node_info[0]['interface_ids'];
220     $nodegroup_ids= $node_info[0]['nodegroup_ids'];
221     $pcu_ids= $node_info[0]['pcu_ids'];
222     $ports= $node_info[0]['ports'];
223
224     // get peer
225     $peer_id= $node_info[0]['peer_id'];
226
227     // gets site info
228     $site_info= $api->GetSites( array( $site_id ) );
229     $site_name= $site_info[0]['name'];
230     $site_nodes= $site_info[0]['node_ids'];
231
232     if( !empty( $site_nodes ) ) {
233       // get site node info basics
234       $site_node_list= $api->GetNodes( $site_nodes );
235
236       foreach( $site_node_list as $s_node ) {
237         $site_node[$s_node['node_id']]= $s_node['hostname'];
238       }
239     }
240
241     // gets slice info for each slice
242     if( !empty( $slice_ids ) )
243       $slice_info= $api->GetSlices( $slice_ids, array( "slice_id", "name" , "peer_id" ) );
244
245     // gets conf file info
246     if( !empty( $conf_file_ids ) )
247       $conf_files= $api->GetConfFiles( $conf_file_ids );
248
249     // get interface info
250     if( !empty( $interface_ids ) )
251       $interfaces= $api->GetInterfaces( $interface_ids );
252
253     // gets nodegroup info
254     if( !empty( $nodegroup_ids ) )
255       $node_groups= $api->GetNodeGroups( $nodegroup_ids );
256
257     // xxx Thierry : disabling call to GetEvents, that gets the session deleted in the DB
258     // gets events 
259     //  $filter= array( "object_type"=>"Node", "object_id"=>$node_id );
260     //  $fields= array( "event_id", "person_id", "fault_code", "call_name", "call", "message", "time" );
261     //
262     //  $event_info= $api->GetEvents( $filter, $fields );
263
264     // gets pcu and port info key to both is $pcu_id
265     if( !empty( $pcu_ids ) )
266       $PCUs= $api->GetPCUs( $pcu_ids );
267
268
269     // display node info
270     if ( $peer_id) {
271       echo "<div class=plc-foreign>";
272     }
273   
274     drupal_set_title("Node " . $hostname . " details");
275
276     $is_admin = in_array( 10, $_roles );
277     $is_pi = in_array( 20, $_roles );
278     $is_tech = in_array( 40, $_roles );
279     $in_site = in_array( $site_id, $_person['site_ids'] );
280
281     // available actions
282     if ( ! $peer_id  && ( $is_admin  || ( ($is_pi||$is_tech) && $in_site ) ) )  {
283       
284       // the javascript callback we set on the form; this
285       // (*) checks whether we clicked on 'delete'
286       // (*) in this case performs a javascript 'confirm'
287       // (*) then, notice that if we select delete, then cancel, we can select back 'Choose action' 
288       //     so submit only when value is not empty
289       $change='if (document.basic.action.value=="delete") if (! confirm("Are you sure you want to delete ' . $hostname . ' ? ") ) return false; if (document.basic.action.value!="") submit();';
290     
291       echo "<table><tr><td>";
292       if ($is_admin) {
293         echo plc_event_button("Node","node",$node_id);
294         echo "</td><td>";
295       }
296       echo plc_comon_button("node_id",$node_id);
297       echo "</td><td>";
298       echo "<form name='basic' action='/db/nodes/node_actions.php' method='post'>\n";
299       echo "<input type=hidden name='node_id' value='$node_id'></input>\n";
300       echo "<select name='action' onChange='$change'>\n";
301       echo "<option value='' selected='selected'> Choose Action </option>\n";
302       echo "<option value='prompt-update'> Update $hostname </option>\n";
303       echo "<option value='delete'> Delete $hostname </option>\n";
304       echo "</select></form>\n";
305
306       echo "</td></tr></table>";
307     }    
308
309     echo "<hr />";
310     echo "<table><tbody>\n";
311
312     echo "<tr><th>Hostname: </th><td> $hostname </td></tr>\n";
313     echo "<tr><th>Model: </th><td> $model</td></tr>\n";
314     echo "<tr><th>Version: </th><td> $version</td></tr>\n";
315     
316     echo "<tr><th>Boot State: </th><td>";
317     if ($peer_id) {
318       echo $boot_state;
319     } else {
320       echo "<form name='bootstate' action='/db/nodes/node_actions.php' method=post>\n";
321       echo "<input type=hidden name='node_id' value='$node_id'>\n";
322       echo "<input type=hidden name='action' value='boot-state'>\n";
323       echo "<select name='boot_state' onChange=\"submit();\">\n";
324
325       $states= array( 'boot'=>'Boot', 'dbg'=>'Debug', 'inst'=>'Install', 'rins'=>'Reinstall', 'rcnf'=>'Reconfigure', 'new'=>'New' );
326
327       foreach( $states as $key => $val ) {
328         echo "<option value='$key'";
329       
330         if( $key == $boot_state )
331           echo " selected";
332       
333         echo ">$val</option>\n";
334       
335       }
336   
337       echo "</select></input></form>";
338     }
339     echo "</td></tr>\n";
340
341     if ( ! $peer_id  && ( $is_admin  || ( ($is_pi||$is_tech) && $in_site ) ) )  {
342       // handle legacy API
343       if ( ! method_exists ($api,"GetBootMedium")) {
344         $new_api_only=" disabled='disabled' ";
345       }
346
347       echo "<tr><th>Download </th><td>";
348       echo "<form name='download' action='/db/nodes/node_actions.php' method='post'>\n";
349       echo "<input type=hidden name='node_id' value='$node_id'></input>\n";
350       echo "<select name='action' onChange='submit();'>\n";
351       echo "<option value='' selected='selected'> Download Mode </option>\n";
352       echo "<option value='' disabled='disabled'> -- All in one images -- </option>"; 
353       echo "<option value='download-node-iso' $new_api_only> Download ISO image for $hostname</option>\n";
354       echo "<option value='download-node-usb' $new_api_only> Download USB image for $hostname</option>\n";
355       echo "<option value='' disabled='disabled'> -- Floppy + generic image -- </option>"; 
356       echo "<option value='download-node-floppy'> Download Floppy file for $hostname</option>\n";
357       echo "<option value='download-generic-iso' $new_api_only> Download generic ISO image (requires floppy) </option>\n";
358       echo "<option value='download-generic-usb' $new_api_only> Download generic USB image (requires floppy) </option>\n";
359       echo "</select></form>";
360       echo "</td></tr>\n";
361
362     }
363
364     // site info and all site nodes
365     echo "<tr><td colspan=2>&nbsp;</td></tr>\n";
366     echo "<tr><th>Site: </th><td> <a href='/db/sites/index.php?id=$site_id'>$site_name</a></td></tr>\n";
367     echo "<tr><th>All site nodes: </th><td>";
368     if (empty($site_node)) {
369       echo "<span class='plc-warning'>Site has no node</span>";
370     } else {
371       foreach( $site_node as $key => $val ) {
372         echo "<a href=index.php?id=$key>$val</a><br />";
373       }
374     }
375     echo "</td></tr>\n";
376
377     echo "</tbody></table><br />\n";
378
379     if ( ! $peer_id ) {
380
381       echo "<hr />\n";
382
383       // display interfaces
384       if( $interfaces ) {
385         echo "<p><table class='list_set' border=0 cellpadding=2>\n";
386         echo "<caption class='list_set'>Interfaces</caption>\n";
387         echo "<thead><tr class='list_set'>";
388         // placeholder for the delete buttons
389         if ( $is_admin || ($is_pi && $in_site)) {
390           echo "<th class='list_set'></th>";
391         }
392         echo "<th class='list_set'>IP Address</th><th class='list_set'>Method</th><th class='list_set'>Type</th><th class='list_set'>MAC</th><th class='list_set'>Bandwidth Limit</th></tr></thead><tbody>\n";
393
394         foreach( $interfaces as $interface ) {
395           $nn_id= $interface['interface_id'];
396           $nn_ip= $interface['ip'];
397           $nn_broad= $interface['broadcast'];
398           $nn_primary= $interface['is_primary'];
399           $nn_network= $interface['network'];
400           $nn_dns1= $interface['dns1'];
401           $nn_dns2= $interface['dns2'];
402           $nn_hostname= $interface['hostname'];
403           $nn_netmaks= $interface['netmask'];
404           $nn_gatewary= $interface['gateway'];
405           $nn_mac= $interface['mac'];
406           $nn_bwlimit= $interface['bwlimit'];
407           $nn_type= $interface['type'];
408           $nn_method= $interface['method'];
409
410           echo "<tr class='list_set'>";
411           if ( $is_admin || ($is_pi && $in_site)) {
412             echo "<td class='list_set'>";
413             if (!$nn_primary) {
414               echo plc_delete_link_button('interfaces.php?id=' . $nn_id . '&delete=1&submitted=1', '\\nInterface ' . $nn_ip);
415             } else {
416               echo '<span title="This interface is primary"> P </span>';
417             }
418             echo "</td>";
419           }
420           echo "<td class='list_set'>";
421           if( $is_admin || $is_pi || $is_tech ) {
422             echo "<a href='interfaces.php?id=$nn_id'>$nn_ip</a>";
423           } else {
424             echo "</td><td class='list_set'>$nn_ip</td>";
425           }
426           echo "<td class='list_set'>$nn_method</td><td class='list_set'>$nn_type</td><td class='list_set'>$nn_mac</td><td class='list_set'>$nn_bwlimit</td></tr>\n";
427         }
428
429         echo "</tbody></table>\n";
430
431       } else {
432         echo "<p><span class='plc-warning'>No interface</span>.  Please add an interface to make this a usable PLC node</p>.\n";
433       }
434
435       echo "<br /><a href='interfaces.php?node_id=$node_id'>Add an interface</a>.\n";
436       echo "<br /><hr />\n";
437     }
438
439     // display node group info
440     if( !empty( $node_groups ) ) {
441
442       echo "<p><table border=0 cellpadding=3>\n<caption>Node Groups</caption>\n<thead><tr><th>Name</th><th>Description</th>";
443       if( in_array( 10, $_roles ) ) echo "<th></th><th></th>";
444       echo "</tr></thead><tbody>\n";
445
446       foreach( $node_groups as $node_group ) {
447         echo "<tr><td><a href='/db/nodes/node_groups.php?id=". $node_group['nodegroup_id'] ."'>". $node_group['name'] ."</a></td><td>". $node_group['description'] ."</td>";
448
449         if( in_array( '10', $_roles ) || ( in_array( 20, $_roles ) && in_array( $site_id, $_person['site_ids'] ) ) || ( in_array( 40, $_roles ) && in_array( $site_id, $_person['site_ids'] ) ) ) 
450           echo "<td><a href='node_groups.php?nodegroup_id=". $node_group['nodegroup_id'] ."'>Update</a></td><td><a href='node_groups.php?remove=$node_id&nodegrop_id=". $node_group['nodegroup_id'] ."' onclick=\"javascript:return confirm('Are you sure you want to remove ". $hostname ." from ". $node_group['name'] ."?')\">remove</a></td>";
451
452         echo "</tr>\n";
453
454       }
455       echo "</tbody></table><br />\n";
456
457     } else {
458       echo "<p><span class='plc-warning'>This node is not in any nodegroup.</span></p>\n";
459     }    
460
461     // select list for adding to node group
462     // get nodegroup info
463     $full_ng_info= $api->GetNodeGroups( NULL );
464     if( empty( $node_groups ) ) {
465       $person_ng= $full_ng_info;
466     } else {
467       $person_ng= arr_diff( $full_ng_info, $node_groups );
468     }
469
470     sort_nodegroups( $person_ng );
471
472     if( !empty( $person_ng ) ) {
473       echo "<p>Select nodegroup to add this node to.<br />\n";
474       echo "<select name='ng_add' onChange='submit()'>\n<option value=''>Choose node group...</option>\n";
475     
476       foreach( $person_ng as $ngs ) {
477         echo "<option value=". $ngs['nodegroup_id'] .">". $ngs['name'] ."</option>\n";
478       }
479       echo "</select>\n";
480     }
481
482
483     // display slices
484     echo "<br /><hr />\n";
485     if( !empty( $slice_info ) ) {
486       sort_slices( $slice_info );
487       echo paginate( $slice_info, "slice_id", "Slices", 15, "name", "slivers", $node_id );
488     } else {
489       echo "<p><span class='plc-warning'>This node is not associated to any slice.</span></p>\n";
490     }
491
492
493     // display events - disabled, see GetEvents above
494     if( !empty( $event_info ) ) {
495       echo "<br /><hr />\n";
496       echo "<p><table class='list_set' border=0 cellpadding=2>\n<caption class='list_set'>Node Events</caption>\n<thead><tr class='list_set'><th class='list_set'></th><th class='list_set'>Call Name</th><th class='list_set'>Call</th><th class='list_set'>Message</th><th class='list_set'>Time</th></tr></thead><tbody>\n";
497
498       // display event on rows of table
499       foreach( $event_info as $event ) {
500         echo "<tr><td>". $event['call'] ."</td><td>". $event['message'] ."</td><td>". $event['time'] ."</td></tr>\n";
501       }
502       echo "</tbody></table>\n";
503     }
504
505     if ( $peer_id ) {
506       echo "</div>";
507     }
508   }
509   if( $peer_id )
510     echo "<br /></div>";
511   
512   echo "<br /><hr /><p><a href='/db/nodes/index.php'>Back to nodes list</a></div>";
513   
514  }
515
516 // Print footer
517 include 'plc_footer.php';
518
519 ?>