r1933 + worked on ticket:40 (adding multiple racks)
[racktables] / inc / interface.php
1 <?php
2 /*
3 *
4 * This file contains frontend functions for RackTables.
5 *
6 */
7
8 // Interface function's special.
9 $nextorder['odd'] = 'even';
10 $nextorder['even'] = 'odd';
11
12 // Main menu.
13 function renderIndex ()
14 {
15 global $root;
16 ?>
17 <table border=0 cellpadding=0 cellspacing=0 width='100%'>
18 <tr>
19 <td>
20 <div style='text-align: center; margin: 10px; '>
21 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
22 <tr>
23 <td>
24 <h1><a href='<?php echo $root; ?>?page=rackspace'>Rackspace<br>
25 <?php printImageHREF ('rackspace'); ?></a></h1>
26 </td>
27 <td>
28 <h1><a href='<?php echo $root; ?>?page=objects'>Objects<br>
29 <?php printImageHREF ('objects'); ?></a></h1>
30 </td>
31 <td>
32 <h1><a href='<?php echo $root; ?>?page=ipv4space'>IPv4 space<br>
33 <?php printImageHREF ('ipv4space'); ?></a></h1>
34 </td>
35 </tr>
36 </table>
37 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
38 <tr>
39 <td>
40 <h1><a href='<?php echo $root; ?>?page=config'>Configuration<br>
41 <?php printImageHREF ('config'); ?></a></h1>
42 </td>
43 <td>
44 <h1><a href='<?php echo $root; ?>?page=reports'>Reports<br>
45 <?php printImageHREF ('reports'); ?></a></h1>
46 </td>
47 <td>
48 <h1><a href='<?php echo $root; ?>?page=ipv4slb'>IPv4 SLB<br>
49 <?php printImageHREF ('ipv4slb'); ?></a></h1>
50 </td>
51 </tr>
52 </table>
53 </div>
54 </td>
55 </tr>
56 </table>
57 <?php
58 }
59
60 function renderRackspace ()
61 {
62 $tagfilter = getTagFilter();
63 $tagfilter_str = getTagFilterStr ($tagfilter);
64 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
65 renderTagFilterPortlet ($tagfilter, 'rack');
66 echo '</td><td class=pcright>';
67 echo '<table border=0 cellpadding=10 cellpadding=1>';
68 // generate thumb gallery
69 $rackrowList = getRackspace ($tagfilter);
70 global $root, $nextorder;
71 $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
72 $order = 'odd';
73 foreach ($rackrowList as $rackrow)
74 {
75 echo "<tr class=row_${order}><th class=tdleft>";
76 echo "<a href='${root}?page=row&row_id=${rackrow['row_id']}${tagfilter_str}'>";
77 echo "${rackrow['row_name']}</a></th>";
78 $rackList = getRacksForRow ($rackrow['row_id'], $tagfilter);
79 echo "<td><table border=0 cellspacing=5><tr>";
80 foreach ($rackList as $rack)
81 {
82 echo "<td align=center><a href='${root}?page=rack&rack_id=${rack['id']}'>";
83 echo "<img border=0 width=${rackwidth} height=";
84 echo 3 + 3 + $rack['height'] * 2;
85 echo " title='${rack['height']} units'";
86 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
87 echo "<br>${rack['name']}</a></td>";
88 }
89 echo "</tr></table></tr>\n";
90 $order = $nextorder[$order];
91 }
92 echo "</table>\n";
93 echo "</td></tr></table>\n";
94 }
95
96 function renderRow ($row_id)
97 {
98 if ($row_id == 0)
99 {
100 showError ('Invalid row_id', __FUNCTION__);
101 return;
102 }
103 if (($rowInfo = getRackRowInfo ($row_id)) == NULL)
104 {
105 showError ('getRackRowInfo() failed', __FUNCTION__);
106 return;
107 }
108 $tagfilter = getTagFilter();
109 $rackList = getRacksForRow ($row_id, $tagfilter);
110 // Main layout starts.
111 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
112
113 // Left portlet with row information.
114 echo "<tr><td class=pcleft>";
115 startPortlet ($rowInfo['dict_value']);
116 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
117 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
118 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
119 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
120 renderProgressBar (getRSUforRackRow ($rackList));
121 echo "</td></tr>\n";
122 echo "</table><br>\n";
123 finishPortlet();
124
125 echo "</td><td class=pcright rowspan=2>";
126
127 global $root, $nextorder;
128 $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
129 $order = 'odd';
130 startPortlet ('Racks');
131 echo "<table border=0 cellspacing=5 align='center'><tr>";
132 foreach ($rackList as $rack)
133 {
134 echo "<td align=center class=row_${order}><a href='${root}?page=rack&rack_id=${rack['id']}'>";
135 echo "<img border=0 width=" . $rackwidth * getConfigVar ('ROW_SCALE') . " height=";
136 echo (3 + 3 + $rack['height'] * 2) * getConfigVar ('ROW_SCALE');
137 echo " title='${rack['height']} units'";
138 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
139 echo "<br>${rack['name']}</a></td>";
140 $order = $nextorder[$order];
141 }
142 echo "</tr></table>\n";
143 finishPortlet();
144 echo "</td></tr>";
145
146 echo "<tr><td class=pcleft>";
147 renderTagFilterPortlet ($tagfilter, 'rack', 'row_id', $row_id);
148 echo "</td></tr></table>";
149 }
150
151 function showError ($info = '', $funcname = 'N/A')
152 {
153 global $root;
154 echo "<div class=msg_error>An error has occured in function [${funcname}]. ";
155 if (empty ($info))
156 echo 'No additional information is available.';
157 else
158 echo "Additional information:<br><p>\n<pre>\n${info}\n</pre></p>";
159 echo "Go back or try starting from <a href='${root}'>index page</a>.<br></div>\n";
160 }
161
162 // This function renders rack as HTML table.
163 function renderRack ($rack_id = 0, $hl_obj_id = 0)
164 {
165 if ($rack_id == 0)
166 {
167 showError ('Invalid rack_id', __FUNCTION__);
168 return;
169 }
170 if (($rackData = getRackData ($rack_id)) == NULL)
171 {
172 showError ('getRackData() failed', __FUNCTION__);
173 return;
174 }
175 global $root, $pageno, $tabno;
176 markAllSpans ($rackData);
177 if ($hl_obj_id > 0)
178 highlightObject ($rackData, $hl_obj_id);
179 markupObjectProblems ($rackData);
180 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
181 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
182 echo "<center><table border=0><tr valign=middle>";
183 echo "<td><h2><a href='${root}?page=row&row_id=${rackData['row_id']}'>${rackData['row_name']}</a> :</h2></td>";
184 // FIXME: use 'bypass'?
185 if ($prev_id != NULL)
186 {
187 echo "<td><a href='${root}?page=rack&rack_id=${prev_id}'>";
188 printImageHREF ('prev', 'previous rack');
189 echo "</a></td>";
190 }
191 echo "<td><h2><a href='${root}?page=rack&rack_id=${rackData['id']}'>${rackData['name']}</a></h2></td>";
192 if ($next_id != NULL)
193 {
194 echo "<td><a href='${root}?page=rack&rack_id=${next_id}'>";
195 printImageHREF ('next', 'next rack');
196 echo "</a></td>";
197 }
198 echo "</h2></td></tr></table>\n";
199 if ($rackData['left_is_front'] == 'yes')
200 $markup = array ('left' => 'Front', 'right' => 'Back');
201 else
202 $markup = array ('left' => 'Back', 'right' => 'Front');
203 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
204 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>${markup['left']}</th>";
205 echo "<th width='50%'>Interior</th><th width='20%'>${markup['right']}</th></tr>\n";
206 for ($i = $rackData['height']; $i > 0; $i--)
207 {
208 echo '<tr><th>' . ($rackData['bottom_is_unit1'] == 'yes' ? $i : $rackData['height'] - $i + 1) . '</th>';
209 for ($locidx = 0; $locidx < 3; $locidx++)
210 {
211 if (isset ($rackData[$i][$locidx]['skipped']))
212 continue;
213 $state = $rackData[$i][$locidx]['state'];
214 echo "<td class=state_${state}";
215 if (isset ($rackData[$i][$locidx]['hl']))
216 echo $rackData[$i][$locidx]['hl'];
217 if (isset ($rackData[$i][$locidx]['colspan']))
218 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
219 if (isset ($rackData[$i][$locidx]['rowspan']))
220 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
221 echo ">";
222 switch ($state)
223 {
224 case 'T':
225 $objectData = getObjectInfo ($rackData[$i][$locidx]['object_id']);
226 if (!empty ($objectData['asset_no']))
227 $prefix = "<div title='${objectData['asset_no']}";
228 else
229 $prefix = "<div title='no asset tag";
230 // Don't tell about label, if it matches common name.
231 if ($objectData['name'] != $objectData['label'] and !empty ($objectData['label']))
232 $suffix = ", visible label is \"${objectData['label']}\"'>";
233 else
234 $suffix = "'>";
235 echo $prefix . $suffix;
236 echo "<a href='${root}?page=object&object_id=${objectData['id']}'>${objectData['dname']}</a></div>";
237 break;
238 case 'A':
239 echo '<div title="This rackspace does not exist">&nbsp;</div>';
240 break;
241 case 'F':
242 echo '<div title="Free rackspace">&nbsp;</div>';
243 break;
244 case 'U':
245 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
246 break;
247 default:
248 echo '<div title="No data">&nbsp;</div>';
249 break;
250 }
251 echo '</td>';
252 }
253 echo "</tr>\n";
254 }
255 echo "</table></center>\n";
256 }
257
258 function renderNewObjectForm ()
259 {
260 global $pageno, $tabno;
261
262 // Look for current submit.
263 if (isset ($_REQUEST['got_data']))
264 {
265 $log = array();
266 assertUIntArg ('object_type_id', __FUNCTION__);
267 assertStringArg ('object_name', __FUNCTION__, TRUE);
268 assertStringArg ('object_label', __FUNCTION__, TRUE);
269 assertStringArg ('object_barcode', __FUNCTION__, TRUE);
270 assertStringArg ('object_asset_no', __FUNCTION__, TRUE);
271 $type_id = $_REQUEST['object_type_id'];
272 $name = $_REQUEST['object_name'];
273 $label = $_REQUEST['object_label'];
274 $asset_no = $_REQUEST['object_asset_no'];
275 $barcode = $_REQUEST['object_barcode'];
276
277 if (commitAddObject ($name, $label, $barcode, $type_id, $asset_no) === TRUE)
278 $log[] = array ('code' => 'success', 'message' => "Added new object '${name}'");
279 else
280 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
281 printLog ($log);
282 }
283
284 // Render a form for the next.
285 startPortlet ('Object attributes');
286 echo '<form>';
287 echo "<input type=hidden name=page value=${pageno}>";
288 echo "<input type=hidden name=tab value=${tabno}>";
289 echo '<table border=0 align=center>';
290 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
291 $typelist = getObjectTypeList();
292 $typelist[0] = 'select type...';
293 printSelect ($typelist, 'object_type_id', getConfigVar ('DEFAULT_OBJECT_TYPE'));
294 echo "</td></tr>\n";
295 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name></td></tr>\n";
296 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label></td></tr>\n";
297 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no></td></tr>\n";
298 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode></td></tr>\n";
299 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Create'></td></tr>\n";
300 echo '</form></table>';
301 finishPortlet();
302 }
303
304 function renderNewRackForm ($row_id)
305 {
306 global $pageno, $tabno;
307 $log = array();
308
309 // Look for current submit.
310 if (isset ($_REQUEST['got_data']))
311 {
312 assertStringArg ('rack_name', __FUNCTION__);
313 assertUIntArg ('rack_height', __FUNCTION__);
314 assertStringArg ('rack_comment', __FUNCTION__, TRUE);
315 $name = $_REQUEST['rack_name'];
316
317 if (commitAddRack ($name, $_REQUEST['rack_height'], $row_id, $_REQUEST['rack_comment']) === TRUE)
318 $log[] = array ('code' => 'success', 'message' => "Added new rack '${name}'");
319 else
320 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddRack() failed');
321 }
322 elseif (isset ($_REQUEST['got_mdata']))
323 {
324 assertUIntArg ('rack_height', __FUNCTION__);
325 assertStringArg ('rack_names', __FUNCTION__, TRUE);
326 // copy-and-paste from renderAddMultipleObjectsForm()
327 $names1 = explode ('\n', $_REQUEST['rack_names']);
328 $names2 = array();
329 foreach ($names1 as $line)
330 {
331 $parts = explode ('\r', $line);
332 reset ($parts);
333 if (empty ($parts[0]))
334 continue;
335 else
336 $names2[] = rtrim ($parts[0]);
337 }
338 foreach ($names2 as $cname)
339 if (commitAddRack ($cname, $_REQUEST['rack_height'], $row_id, '') === TRUE)
340 $log[] = array ('code' => 'success', 'message' => "Added new rack '${cname}'");
341 else
342 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddRack() failed');
343 }
344 printLog ($log);
345
346 // Render a form for the next.
347 startPortlet ('Add one');
348 echo '<form>';
349 echo "<input type=hidden name=page value=${pageno}>";
350 echo "<input type=hidden name=tab value=${tabno}>";
351 echo "<input type=hidden name=row_id value=${row_id}>";
352 echo '<table border=0 align=center>';
353 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
354 if ($defh == 0)
355 $defh = '';
356 echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td></tr>\n";
357 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height tabindex=2 value='${defh}'></td></tr>\n";
358 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
359 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Add'></td></tr>\n";
360 echo '</form></table>';
361 finishPortlet();
362
363 startPortlet ('Add many');
364 echo '<form>';
365 echo "<input type=hidden name=page value=${pageno}>";
366 echo "<input type=hidden name=tab value=${tabno}>";
367 echo "<input type=hidden name=row_id value=${row_id}>";
368 echo '<table border=0 align=center>';
369 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
370 if ($defh == 0)
371 $defh = '';
372 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height value='${defh}'></td></tr>\n";
373 echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
374 echo "<tr><td class=submit colspan=2><input type=submit name=got_mdata value='Add'></td></tr>\n";
375 echo '</form></table>';
376 finishPortlet();
377 }
378
379 function renderEditObjectForm ($object_id)
380 {
381 showMessageOrError();
382 // Handle submit.
383 if (isset ($_REQUEST['got_data']))
384 {
385 $log = array();
386 // object_id is already verified by page handler
387 assertUIntArg ('object_type_id', __FUNCTION__);
388 assertStringArg ('object_name', __FUNCTION__, TRUE);
389 assertStringArg ('object_label', __FUNCTION__, TRUE);
390 assertStringArg ('object_barcode', __FUNCTION__, TRUE);
391 assertStringArg ('object_asset_no', __FUNCTION__, TRUE);
392 $type_id = $_REQUEST['object_type_id'];
393 if (isset ($_REQUEST['object_has_problems']) and $_REQUEST['object_has_problems'] == 'on')
394 $has_problems = 'yes';
395 else
396 $has_problems = 'no';
397 $name = $_REQUEST['object_name'];
398 $label = $_REQUEST['object_label'];
399 $barcode = $_REQUEST['object_barcode'];
400 $asset_no = $_REQUEST['object_asset_no'];
401 $comment = $_REQUEST['object_comment'];
402
403 if (commitUpdateObject ($object_id, $name, $label, $barcode, $type_id, $has_problems, $asset_no, $comment) === TRUE)
404 $log[] = array ('code' => 'success', 'message' => "Updated object '${name}'");
405 else
406 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitUpdateObject() failed');
407 // Invalidate thumb cache of all racks objects could occupy.
408 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
409 resetThumbCache ($rack_id);
410 printLog ($log);
411 }
412
413 global $pageno, $tabno;
414 $object = getObjectInfo ($object_id);
415 if ($object == NULL)
416 {
417 showError ('getObjectInfo() failed', __FUNCTION__);
418 return;
419 }
420
421 // Render a form for the next submit;
422 echo '<table border=0 width=100%><tr>';
423
424 echo '<td class=pcleft>';
425 startPortlet ('Static attributes');
426 echo '<form method=post>';
427 echo "<input type=hidden name=page value=${pageno}>";
428 echo "<input type=hidden name=tab value=${tabno}>";
429 echo "<input type=hidden name=object_id value=${object_id}>";
430 echo "<input type=hidden name=got_data value=1>";
431 echo '<table border=0 align=center>';
432 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
433 printSelect (getObjectTypeList(), 'object_type_id', $object['objtype_id']);
434 echo "</td></tr>\n";
435 // Common attributes.
436 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
437 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
438 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no value='${object['asset_no']}'></td></tr>\n";
439 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
440 echo "<tr><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
441 if ($object['has_problems'] == 'yes')
442 echo ' checked';
443 echo "></td></tr>\n";
444 echo "<tr><td colspan=2><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
445 echo "<tr><th class=submit colspan=2>";
446 printImageHREF ('SAVE', 'Save changes', TRUE);
447 echo "</td></tr>\n";
448 echo '</form></table><br>';
449 finishPortlet();
450 echo '</td>';
451
452 // Optional attributes.
453 echo '<td class=pcright>';
454 startPortlet ('Optional attributes');
455 $values = getAttrValues ($object_id);
456 global $root;
457 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
458 echo "<tr><th>&nbsp;</th><th>Attribute</th><th>Value</th><th>&nbsp;</th></tr>\n";
459 echo "<form method=post action='${root}process.php'>\n";
460 echo "<input type=hidden name=page value=${pageno}>\n";
461 echo "<input type=hidden name=tab value=${tabno}>\n";
462 echo "<input type=hidden name=op value=upd>\n";
463 echo "<input type=hidden name=object_id value=${object_id}>\n";
464 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
465
466 $i = 0;
467 foreach ($values as $record)
468 {
469 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
470 echo '<tr><td>';
471 if (!empty ($record['value']))
472 {
473 echo "<a href=${root}process.php?page=${pageno}&tab=${tabno}&op=del&object_id=${object_id}&attr_id=${record['id']}>";
474 printImageHREF ('clear', 'Clear value');
475 echo '</a>';
476 }
477 else
478 echo '&nbsp;';
479 echo '</td>';
480 echo "<td class=tdright>${record['name']}:</td><td class=tdleft>";
481 switch ($record['type'])
482 {
483 case 'uint':
484 case 'float':
485 case 'string':
486 echo "<input type=text name=${i}_value value='${record['value']}'>";
487 break;
488 case 'dict':
489 $chapter = readChapter ($record['chapter_name']);
490 $chapter[0] = '-- NOT SET --';
491 printSelect ($chapter, "${i}_value", $record['key']);
492 break;
493 }
494 echo "</td></tr>\n";
495 $i++;
496 }
497 echo "<tr><td colspan=3>";
498 printImageHREF ('SAVE', 'Save changes', TRUE);
499 echo "</td></tr>\n";
500 echo "</form>";
501 echo "</table>\n";
502 finishPortlet();
503 echo '</td>';
504
505 echo '</tr><tr>';
506
507 echo '<td colspan=2>';
508 startPortlet ('history');
509 renderHistory ($pageno, $object_id);
510 finishPortlet();
511 echo '</td>';
512
513 echo '</tr></table>';
514 }
515
516 // This is a clone of renderEditObjectForm().
517 function renderEditRackForm ($rack_id)
518 {
519 // Handle submit.
520 if (isset ($_REQUEST['got_data']))
521 {
522 $log = array();
523 assertUIntArg ('rack_row_id', __FUNCTION__);
524 assertUIntArg ('rack_height', __FUNCTION__);
525 assertStringArg ('rack_name', __FUNCTION__);
526 assertStringArg ('rack_comment', __FUNCTION__, TRUE);
527 $row_id = $_REQUEST['rack_row_id'];
528 $height = $_REQUEST['rack_height'];
529 $name = $_REQUEST['rack_name'];
530 $comment = $_REQUEST['rack_comment'];
531
532 if (commitUpdateRack ($rack_id, $name, $height, $row_id, $comment) === TRUE)
533 $log[] = array ('code' => 'success', 'message' => "Updated rack '${name}'");
534 else
535 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitUpdateRack() failed');
536 resetThumbCache ($rack_id);
537 printLog ($log);
538 }
539
540 global $pageno, $tabno;
541 $rack = getRackData ($rack_id);
542 if ($rack == NULL)
543 {
544 showError ('getRackData() failed', __FUNCTION__);
545 return;
546 }
547
548 // Render a form for the next.
549 startPortlet ('Rack attributes');
550 echo '<form>';
551 echo "<input type=hidden name=page value=${pageno}>";
552 echo "<input type=hidden name=tab value=${tabno}>";
553 echo "<input type=hidden name=rack_id value=${rack_id}>";
554 echo '<table border=0 align=center>';
555 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
556 printSelect (readChapter ('RackRow'), 'rack_row_id', $rack['row_id']);
557 echo "</td></tr>\n";
558 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
559 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
560 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
561 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
562 echo '</form></table><br>';
563 finishPortlet();
564
565 startPortlet ('History');
566 renderHistory ($pageno, $rack_id);
567 finishPortlet();
568 }
569
570 // This is a helper for creators and editors.
571 function printSelect ($rowList, $select_name, $selected_id = 1)
572 {
573 // First collect all data for OPTGROUPs, then ouput it and dump
574 // the rest of records as is.
575 $optgroup = array();
576 $other = array();
577 foreach ($rowList as $dict_key => $dict_value)
578 {
579 if (strpos ($dict_value, '%GSKIP%') !== FALSE)
580 {
581 $tmp = explode ('%GSKIP%', $dict_value, 2);
582 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
583 }
584 elseif (strpos ($dict_value, '%GPASS%') !== FALSE)
585 {
586 $tmp = explode ('%GPASS%', $dict_value, 2);
587 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
588 }
589 else
590 $other[$dict_key] = $dict_value;
591 }
592 echo "<select name=${select_name}>";
593 if (!count ($optgroup))
594 {
595 foreach ($other as $dict_key => $dict_value)
596 {
597 echo "<option value=${dict_key}";
598 if ($dict_key == $selected_id)
599 echo ' selected';
600 echo ">${dict_value}</option>";
601 }
602 }
603 else
604 {
605 foreach ($optgroup as $groupname => $groupdata)
606 {
607 echo "<optgroup label='${groupname}'>";
608 foreach ($groupdata as $dict_key => $dict_value)
609 {
610 echo "<option value=${dict_key}";
611 if ($dict_key == $selected_id)
612 echo ' selected';
613 echo ">${dict_value}</option>";
614 }
615 echo "</optgroup>\n";
616 }
617 if (count ($other))
618 {
619 echo "<optgroup label='other'>\n";
620 foreach ($other as $dict_key => $dict_value)
621 {
622 echo "<option value=${dict_key}";
623 if ($dict_key == $selected_id)
624 echo ' selected';
625 echo ">${dict_value}</option>";
626 }
627 echo "</optgroup>\n";
628 }
629 }
630 echo "</select>";
631 }
632
633 // used by renderGridForm() and renderRackPage()
634 function renderRackInfoPortlet ($rackData)
635 {
636 global $root;
637 startPortlet ('summary');
638 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
639 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
640 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
641 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
642 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
643 renderProgressBar (getRSUforRack ($rackData));
644 echo "</td></tr>\n";
645 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
646 echo getObjectCount ($rackData);
647 echo "</td></tr>\n";
648 printTagTRs ("${root}?page=rackspace&");
649 if (!empty ($rackData['comment']))
650 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
651 echo '</table>';
652 finishPortlet();
653 }
654
655 // This is a universal editor of rack design/waste.
656 function renderGridForm ($rack_id = 0, $filter, $header, $submit, $state1, $state2)
657 {
658 if ($rack_id == 0)
659 {
660 showError ('Invalid rack_id', __FUNCTION__);
661 return;
662 }
663 if (($rackData = getRackData ($rack_id)) == NULL)
664 {
665 showError ('getRackData() failed', __FUNCTION__);
666 return;
667 }
668
669 global $root, $pageno, $tabno;
670 $filter ($rackData);
671 markupObjectProblems ($rackData);
672
673 // Process form submit.
674 if (isset ($_REQUEST['do_update']))
675 {
676 $log[] = processGridForm ($rackData, $state1, $state2);
677 printLog ($log);
678 $rackData = getRackData ($rack_id);
679 $filter ($rackData);
680 markupObjectProblems ($rackData);
681 }
682
683 // Render the result whatever it is.
684 // Main layout.
685 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
686 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
687
688 // Left column with information portlet.
689 echo "<tr><td class=pcleft height='1%' width='50%'>";
690 renderRackInfoPortlet ($rackData);
691 echo "</td>\n";
692 echo "<td class=pcright>";
693
694 // Grid form.
695 startPortlet ($header);
696 echo "<center>\n";
697 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
698 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
699 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
700 echo "<form method=post action='${root}?'>\n";
701 echo "<input type=hidden name=page value=${pageno}>\n";
702 echo "<input type=hidden name=tab value=${tabno}>\n";
703 echo "<input type=hidden name=rack_id value=${rack_id}>\n";
704 markupAtomGrid ($rackData, $state2);
705 renderAtomGrid ($rackData);
706 echo "</table></center>\n";
707 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
708 finishPortlet();
709 echo "</td></tr></table>\n";
710 }
711
712 function renderRackDesign ($rack_id)
713 {
714 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
715 }
716
717 function renderRackProblems ($rack_id = 0)
718 {
719 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
720 }
721
722 function startPortlet ($title = '')
723 {
724 echo "<div class=portlet><h2>${title}</h2>";
725 }
726
727 function finishPortlet ()
728 {
729 echo "</div>\n";
730 }
731
732 function printRefsOfType ($refs, $type, $eq)
733 {
734 global $root;
735 $gotone=0;
736 foreach ($refs as $ref)
737 {
738 if ($eq($ref['type'], $type))
739 {
740 if ($gotone) echo ', ';
741 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
742 if (!empty ($ref['name']))
743 echo $ref['name'] . '@';
744 echo "${ref['object_name']}</a>";
745 $gotone=1;
746 }
747 }
748 }
749
750 function renderRackObject ($object_id = 0)
751 {
752 global $root;
753 if ($object_id <= 0)
754 {
755 showError ('Invalid object_id', __FUNCTION__);
756 return;
757 }
758 $info = getObjectInfo ($object_id);
759 if ($info == NULL)
760 {
761 showError ('getObjectInfo() failed', __FUNCTION__);
762 return;
763 }
764 // Main layout starts.
765 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
766 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
767 // left column with uknown number of portlets
768 echo "<tr><td class=pcleft>";
769 startPortlet ('Object information');
770 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
771 if (!empty ($info['name']))
772 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
773 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
774 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
775 echo "<tr><th width='50%' class=tdright>Object type:</th>";
776 echo "<td class=tdleft><a href='${root}?page=objgroup&group_id=${info['objtype_id']}'>${info['objtype_name']}</a></td></tr>\n";
777 if (!empty ($info['asset_no']))
778 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
779 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('REQUIRE_ASSET_TAG_FOR'))))
780 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
781 if (!empty ($info['label']))
782 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
783 if (!empty ($info['barcode']))
784 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
785 if ($info['has_problems'] == 'yes')
786 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
787 foreach (getAttrValues ($object_id, TRUE) as $record)
788 if (!empty ($record['value']))
789 echo "<tr><th width='50%' class=opt_attr_th>${record['name']}:</th><td class=tdleft>${record['a_value']}</td></tr>\n";
790 printTagTRs ("${root}?page=objgroup&group_id=${info['objtype_id']}&");
791 echo "</table><br>\n";
792 finishPortlet();
793
794 if (!empty ($info['comment']))
795 {
796 startPortlet ('Comment');
797 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
798 finishPortlet ();
799 }
800
801 $ports = getObjectPortsAndLinks ($object_id);
802 if (count ($ports))
803 {
804 startPortlet ('Ports and links');
805 usort($ports, 'sortByName');
806 if ($ports)
807 {
808 $hl_port_id = 0;
809 if (isset ($_REQUEST['hl_port_id']))
810 {
811 assertUIntArg ('hl_port_id', __FUNCTION__);
812 $hl_port_id = $_REQUEST['hl_port_id'];
813 }
814 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
815 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
816 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
817 foreach ($ports as $port)
818 {
819 echo '<tr';
820 if ($hl_port_id == $port['id'])
821 echo ' class=port_highlight';
822 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
823 echo "<td>${port['l2address']}</td>";
824 if ($port['remote_object_id'])
825 {
826 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
827 echo "<td>${port['remote_name']}</td>";
828 }
829 elseif (!empty ($port['reservation_comment']))
830 {
831 echo "<td><b>Reserved;</b></td>";
832 echo "<td>${port['reservation_comment']}</td>";
833 }
834 else
835 echo '<td>&nbsp;</td><td>&nbsp;</td>';
836 echo "</tr>\n";
837 }
838 echo "</table><br>\n";
839 }
840 finishPortlet();
841 }
842 $addresses = getObjectAddresses ($object_id);
843 usort($addresses, 'sortAddresses');
844 if (count ($addresses))
845 {
846 startPortlet ('IPv4 addresses');
847 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
848 echo "<tr><th>Interface name</th><th>IP Address</th><th>Description</th><th>Misc</th></tr>\n";
849 foreach ($addresses as $addr)
850 {
851 if (strlen($addr['address_name'])>40)
852 $address_name = substr($addr['address_name'],0,38).'...';
853 else
854 $address_name = $addr['address_name'];
855
856 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
857 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
858 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
859 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
860
861 if ($addr['address_reserved']=='yes')
862 $class='trerror';
863 elseif ($addr['type']!='virtual' && $regnum>0)
864 $class='trerror';
865 elseif ($addr['type']=='regular' && $sharednum>0)
866 $class='trerror';
867 else
868 $class='';
869
870 echo "<tr class='$class'><td class=tdleft>${addr['name']}</td><td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td><td class='description'>$address_name</td><td class=tdleft>\n";
871
872 if ($addr['address_reserved']=='yes')
873 echo "<b>Reserved;</b> ";
874
875 if ($addr['type'] == 'virtual')
876 {
877 echo "<b>V</b>";
878 if ($notvirtnum > 0)
879 {
880 echo " Owners: ";
881 printRefsOfType($addr['references'], 'virtual', 'neq');
882 }
883 }
884 elseif ($addr['type'] == 'shared')
885 {
886 echo "<b>S</b>";
887 if ($sharednum > 0)
888 {
889 echo " Peers: ";
890 printRefsOfType($addr['references'], 'shared', 'eq');
891 echo ";";
892 }
893 if ($virtnum > 0)
894 {
895 echo " Virtuals: ";
896 printRefsOfType($addr['references'], 'virtual', 'eq');
897 echo ";";
898 }
899 if ($regnum > 0)
900 {
901 echo " Collisions: ";
902 printRefsOfType($addr['references'], 'regular', 'eq');
903 }
904
905 }
906 else
907 {
908 if ($virtnum > 0)
909 {
910 echo " Virtuals: ";
911 printRefsOfType($addr['references'], 'virtual', 'eq');
912 echo ";";
913 }
914 if ($notvirtnum > 0)
915 {
916 echo " Collisions: ";
917 printRefsOfType($addr['references'], 'virtual', 'neq');
918 }
919 }
920
921 echo "</td></tr>\n";
922 }
923 echo "</table><br>\n";
924 finishPortlet();
925 }
926
927 $forwards = getNATv4ForObject ($object_id);
928 if (count($forwards['in']) or count($forwards['out']))
929 {
930 startPortlet('NATv4');
931
932 if (count($forwards['out']))
933 {
934
935 echo "<h3>locally performed NAT</h3>";
936
937 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
938 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
939
940 foreach ($forwards['out'] as $pf)
941 {
942 $class='trerrorg';
943 $name='';
944 foreach ($addresses as $addr)
945 if ($addr['ip'] == $pf['localip'])
946 {
947 $class='';
948 $name=$addr['name'];
949 break;
950 }
951
952 echo "<tr class='$class'>";
953
954 echo "<td>${pf['proto']}</td><td class=tdleft>${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
955
956 echo "<td class=tdleft><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
957
958 $address=getIPAddress($pf['remoteip']);
959
960 echo "<td class='description'>";
961 if (count ($address['bonds']))
962 foreach($address['bonds'] as $bond)
963 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
964 elseif (!empty ($pf['remote_addr_name']))
965 echo '(' . $pf['remote_addr_name'] . ')';
966
967 echo "</td><td class='description'>${pf['description']}</td>";
968
969 echo "</tr>";
970 }
971 echo "</table><br><br>";
972 }
973 if (count($forwards['in']))
974 {
975 echo "<h3>arriving NAT connections</h3>";
976
977 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
978 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
979
980 foreach ($forwards['in'] as $pf)
981 {
982 echo "<tr>";
983 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
984
985 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
986
987 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
988 echo "<td class='description'>${pf['description']}</td></tr>";
989 }
990
991 echo "</table><br><br>";
992 }
993 finishPortlet();
994 }
995
996 $pools = getRSPoolsForObject ($object_id);
997 if (count ($pools))
998 {
999 startPortlet ('Real server pools');
1000 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
1001 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th></tr>\n";
1002 foreach ($pools as $vs_id => $info)
1003 {
1004 echo "<tr valign=top><td class=tdleft><a href='${root}?page=vservice&id=${vs_id}'>";
1005 echo buildVServiceName ($info);
1006 echo '</a>';
1007 if (!empty ($info['name']))
1008 echo " (${info['name']})";
1009 echo "</td><td class=tdleft><a href='${root}?page=rspool&pool_id=${info['pool_id']}'>";
1010 echo (empty ($info['pool_name']) ? 'ANONYMOUS' : $info['pool_name']);
1011 echo '</a></td><td class=tdleft>' . $info['rscount'] . '</td>';
1012 echo "<td class=tdleft><pre>${info['vsconfig']}</pre></td>";
1013 echo "<td class=tdleft><pre>${info['rsconfig']}</pre></td>";
1014 echo "</tr>\n";
1015 }
1016 echo "</table>\n";
1017 finishPortlet();
1018 }
1019 echo "</td>\n";
1020
1021 // After left column we have (surprise!) right column with rackspace portled only.
1022 echo "<td class=pcright>";
1023 // rackspace portlet
1024 startPortlet ('Rackspace allocation');
1025 // FIXME: now we call getRackData() twice
1026 $racks = getResidentRacksData ($object_id);
1027 foreach ($racks as $rackData)
1028 renderRack ($rackData['id'], $object_id);
1029 echo '<br>';
1030 finishPortlet();
1031 echo "</td></tr>";
1032 echo "</table>\n";
1033 }
1034
1035 function renderRackMultiSelect ($sname, $racks, $selected)
1036 {
1037 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementById(\"racks\").submit()'>\n";
1038 foreach ($racks as $rack)
1039 {
1040 echo "<option value=${rack['id']}";
1041 if (!(array_search ($rack['id'], $selected) === FALSE))
1042 echo ' selected';
1043 echo">${rack['row_name']}: ${rack['name']}</option>\n";
1044 }
1045 echo "</select>\n";
1046 }
1047
1048 function showMessageOrError ()
1049 {
1050 if (isset($_REQUEST['message']))
1051 echo "<div class=msg_success>${_REQUEST['message']}</div>";
1052 if (isset($_REQUEST['error']))
1053 echo "<div class=msg_error>${_REQUEST['error']}</div>";
1054 }
1055
1056 // This function renders a form for port edition.
1057 function renderPortsForObject ($object_id = 0)
1058 {
1059 global $root, $pageno, $tabno;
1060 if ($object_id <= 0)
1061 {
1062 showError ('Invalid object_id', __FUNCTION__);
1063 return;
1064 }
1065 showMessageOrError();
1066 startPortlet ('Ports and interfaces');
1067 $ports = getObjectPortsAndLinks ($object_id);
1068 usort($ports, 'sortByName');
1069 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1070 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
1071 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1072 foreach ($ports as $port)
1073 {
1074 echo "<form action='${root}process.php'>";
1075 echo "<input type=hidden name=op value=editPort>";
1076 echo "<input type=hidden name=page value='${pageno}'>\n";
1077 echo "<input type=hidden name=tab value='${tabno}'>\n";
1078 echo "<input type=hidden name=port_id value='${port['id']}'>";
1079 echo "<input type=hidden name=object_id value='$object_id'>\n";
1080 echo "<tr><td><a href='${root}process.php?op=delPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=${port['name']}'>";
1081 printImageHREF ('delete', 'Unlink and Delete this port');
1082 echo "</a></td>\n";
1083 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1084 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
1085 echo "<td>${port['type']}</td>\n";
1086 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
1087 if ($port['remote_object_id'])
1088 {
1089 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
1090 echo "<td>${port['remote_name']}</td>";
1091 echo "<td><a href='${root}process.php?op=unlinkPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=";
1092 echo urlencode ($port['name']);
1093 echo "&remote_port_name=${port['remote_name']}&remote_object_name=${port['remote_object_name']}'>";
1094 printImageHREF ('unlink', 'Unlink this port');
1095 echo "</a></td>";
1096 }
1097 elseif (!empty ($port['reservation_comment']))
1098 {
1099 echo "<td><b>Reserved;</b></td>";
1100 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1101 echo "<td><a href='${root}process.php?op=useup&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=${object_id}'>";
1102 printImageHREF ('useup', 'Use up this port');
1103 echo "</a></td>";
1104 }
1105 else
1106 {
1107 echo "<td>&nbsp;</td><td>&nbsp;</td>";
1108 echo "<td>";
1109 echo "<a href='javascript:;' onclick='window.open(\"${root}link_helper.php?port=${port['id']}&type=${port['type_id']}&object_id=$object_id&port_name=";
1110 echo urlencode ($port['name']);
1111 echo "\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
1112 printImageHREF ('link', 'Link this port');
1113 echo "</a> <input type=text name=reservation_comment>";
1114 echo "</td>\n";
1115 }
1116 echo "<td>";
1117 printImageHREF ('save', 'Save changes', TRUE);
1118 echo "</td></form></tr>\n";
1119 }
1120 echo "<form action='${root}process.php'><tr><td>";
1121 printImageHREF ('add', '', TRUE, 104);
1122 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
1123 echo "<td><input type=text size=24 name=port_label tabindex=101></td>";
1124 echo "<input type=hidden name=op value=addPort>\n";
1125 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1126 echo "<input type=hidden name=page value='${pageno}'>\n";
1127 echo "<input type=hidden name=tab value='${tabno}'>\n";
1128 echo "<td><select name='port_type_id' tabindex=102>\n";
1129 $types = getPortTypes();
1130 $default_port_type = getConfigVar ('default_port_type');
1131 foreach ($types as $typeid => $typename)
1132 {
1133 echo "<option value='${typeid}'";
1134 if ($typeid == $default_port_type)
1135 echo " selected";
1136 echo ">${typename}</option>\n";
1137 }
1138 echo "</select></td>";
1139 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
1140 echo "<td colspan=4>&nbsp;</td></tr></form>";
1141 echo "</table><br>\n";
1142 finishPortlet();
1143
1144 startPortlet ('Add/update multiple ports');
1145 echo "<form action=${root}process.php method=post>";
1146 echo "<input type=hidden name=page value='${pageno}'>\n";
1147 echo "<input type=hidden name=tab value='${tabno}'>\n";
1148 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1149 echo "<input type=hidden name=op value=addMultiPorts>";
1150 echo 'Format: <select name=format>';
1151 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1152 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1153 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1154 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1155 echo "</select>";
1156 echo 'Default port type: ';
1157 echo "<select name=port_type>\n";
1158 foreach ($types as $typeid => $typename)
1159 {
1160 echo "<option value='${typeid}'";
1161 if ($typeid == $default_port_type)
1162 echo " selected";
1163 echo ">${typename}</option>\n";
1164 }
1165 echo "</select>";
1166 echo "<input type=submit value='Parse output'><br>\n";
1167 echo "<textarea name=input cols=100 rows=50></textarea><br>\n";
1168 echo '</form>';
1169 finishPortlet();
1170 }
1171
1172 function renderNetworkForObject ($object_id=0)
1173 {
1174 global $root, $pageno, $tabno;
1175 if ($object_id <= 0)
1176 {
1177 showError ('Invalid object_id', __FUNCTION__);
1178 return;
1179 }
1180 showMessageOrError();
1181 startPortlet ('Network Addresses');
1182 $addresses = getObjectAddresses ($object_id);
1183 usort($addresses, 'sortAddresses');
1184 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1185 echo "<tr><th>&nbsp;</th><th>Interface name</th><th>IP Address</th><th>Description</th><th>Type</th><th>Misc</th><th>&nbsp</th></tr>\n";
1186 foreach ($addresses as $addr)
1187 {
1188 if (strlen($addr['address_name'])>40)
1189 $address_name = substr($addr['address_name'],0,38).'...';
1190 else
1191 $address_name = $addr['address_name'];
1192
1193 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
1194 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
1195 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
1196 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
1197
1198 if ($addr['address_reserved']=='yes')
1199 $class='trerror';
1200 elseif ($addr['type']!='virtual' && $regnum>0)
1201 $class='trerror';
1202 elseif ($addr['type']=='regular' && $sharednum>0)
1203 $class='trerror';
1204 else
1205 $class='';
1206
1207 echo "<form action='process.php'>";
1208 echo "<input type=hidden name=page value='${pageno}'>\n";
1209 echo "<input type=hidden name=tab value='${tabno}'>\n";
1210 echo "<input type=hidden name=op value=editAddressFromObject>";
1211 echo "<input type=hidden name=object_id value='$object_id'>";
1212 echo "<input type=hidden name=ip value='${addr['ip']}'>";
1213 echo "<tr class='$class'><td><a href='process.php?op=delAddrFObj&page=${pageno}&tab=${tabno}&ip=${addr['ip']}&object_id=$object_id'>";
1214 printImageHREF ('delete', 'Delete this IPv4 address');
1215 echo "</a></td>";
1216 echo "<td class=tdleft><input type='text' name='bond_name' value='${addr['name']}' size=10></td>";
1217 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
1218 echo "<td class='description'>$address_name</td>\n";
1219 echo "<td><select name='bond_type'>";
1220 foreach (array('regular'=>'Regular', 'virtual'=>'Virtual', 'shared'=>'Shared') as $n => $v)
1221 {
1222 echo "<option value='$n'";
1223 if ($addr['type'] == $n)
1224 echo " selected";
1225 echo ">$v</option>";
1226 }
1227 echo "</td><td>";
1228 if ($addr['address_reserved']=='yes')
1229 echo "<b>Reserved</b>; ";
1230
1231 if ($addr['type'] == 'virtual')
1232 {
1233 if ($notvirtnum > 0)
1234 {
1235 echo " Owners: ";
1236 printRefsOfType($addr['references'], 'virtual', 'neq');
1237 }
1238 }
1239 elseif ($addr['type'] == 'shared')
1240 {
1241 if ($sharednum > 0)
1242 {
1243 echo " Peers: ";
1244 printRefsOfType($addr['references'], 'shared', 'eq');
1245 echo ";";
1246 }
1247 if ($virtnum > 0)
1248 {
1249 echo " Virtuals: ";
1250 printRefsOfType($addr['references'], 'virtual', 'eq');
1251 echo ";";
1252 }
1253 if ($regnum > 0)
1254 {
1255 echo " Collisions: ";
1256 printRefsOfType($addr['references'], 'regular', 'eq');
1257 }
1258
1259 }
1260 else
1261 {
1262 if ($virtnum > 0)
1263 {
1264 echo " Virtuals: ";
1265 printRefsOfType($addr['references'], 'virtual', 'eq');
1266 echo ";";
1267 }
1268 if ($notvirtnum > 0)
1269 {
1270 echo " Collisions: ";
1271 printRefsOfType($addr['references'], 'virtual', 'neq');
1272 }
1273 }
1274
1275 echo "</td><td>";
1276 printImageHREF ('save', 'Save changes', TRUE);
1277 echo "</td></form></tr>\n";
1278 }
1279
1280
1281 echo "<form action='${root}process.php'><tr><td>";
1282 printImageHREF ('add', 'Allocate new address', TRUE, 99);
1283 echo "</td><td class=tdleft>";
1284 echo "<input type='text' size='10' name='name' tabindex=100></td>\n";
1285 echo "<input type=hidden name=page value='${pageno}'>\n";
1286 echo "<input type=hidden name=tab value='${tabno}'>\n";
1287 echo "<input type=hidden name=op value=addAddrFObj>\n";
1288 echo "<input type=hidden name=object_id value='$object_id'>\n";
1289 echo "<td class=tdleft><input type=text name='ip' tabindex=101>\n";
1290 echo "</td><td>&nbsp;</td><td><select name='type' tabindex=102>";
1291 echo "<option value='regular'>Regular</option>";
1292 echo "<option value='virtual'>Virtual</option>";
1293 echo "<option value='shared'>Shared</option>";
1294 echo "</select>";
1295 echo "</td><td colspan=2>&nbsp;</td></tr></form>";
1296 echo "</table><br>\n";
1297 finishPortlet();
1298
1299 }
1300
1301 function printLog ($log)
1302 {
1303 foreach ($log as $record)
1304 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1305 }
1306
1307 /*
1308 The following conditions must be followed:
1309 1. We can mount onto free atoms only. This means: if any record for an atom
1310 already exists in RackSpace, it can't be used for mounting.
1311 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1312 and either delete them before unmounting or refuse to unmount the object.
1313 */
1314
1315 // We extensively use $_REQUEST in the function.
1316 function renderRackSpaceForObject ($object_id = 0)
1317 {
1318 if ($object_id <= 0)
1319 {
1320 showError ('Invalid object_id', __FUNCTION__);
1321 return;
1322 }
1323 $is_submit = isset ($_REQUEST['got_atoms']);
1324 $is_update = isset ($_REQUEST['rackmulti'][0]);
1325 $info = getObjectInfo ($object_id);
1326 if ($info == NULL)
1327 {
1328 showError ('getObjectInfo() failed', __FUNCTION__);
1329 return;
1330 }
1331 // Always process occupied racks plus racks chosen by user. First get racks with
1332 // already allocated rackspace...
1333 $workingRacksData = getResidentRacksData ($object_id);
1334 if ($workingRacksData === NULL)
1335 {
1336 print_r ($workingRacksData);
1337 showError ('getResidentRacksData() failed', __FUNCTION__);
1338 return;
1339 }
1340
1341 // ...and then add those chosen by user (if any).
1342 if ($is_update)
1343 foreach ($_REQUEST['rackmulti'] as $cand_id)
1344 {
1345 if (!isset ($workingRacksData[$cand_id]))
1346 {
1347 $rackData = getRackData ($cand_id);
1348 if ($rackData == NULL)
1349 {
1350 showError ('getRackData() failed', __FUNCTION__);
1351 return NULL;
1352 }
1353 $workingRacksData[$cand_id] = $rackData;
1354 }
1355 }
1356
1357 // Do it only once...
1358 foreach ($workingRacksData as &$rackData)
1359 applyObjectMountMask ($rackData, $object_id);
1360 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1361 unset ($rackData);
1362
1363 // Here we process form submit by trying to save all submitted info to database.
1364 if ($is_submit)
1365 {
1366 $oldMolecule = getMoleculeForObject ($object_id);
1367 $worldchanged = FALSE;
1368 $log = array();
1369 foreach ($workingRacksData as $rack_id => $rackData)
1370 {
1371 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1372 $log[] = $logrecord;
1373 if ($logrecord['code'] != 300)
1374 {
1375 $worldchanged = TRUE;
1376 // Reload our working copy after form processing.
1377 $rackData = getRackData ($rack_id);
1378 if ($rackData == NULL)
1379 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in ', __FUNCTION__);
1380 applyObjectMountMask ($rackData, $object_id);
1381 $workingRacksData[$rack_id] = $rackData;
1382 }
1383 }
1384 if ($worldchanged)
1385 {
1386 // Log a record.
1387 $newMolecule = getMoleculeForObject ($object_id);
1388 $oc = count ($oldMolecule);
1389 $nc = count ($newMolecule);
1390 $omid = $oc ? createMolecule ($oldMolecule) : 'NULL';
1391 $nmid = $nc ? createMolecule ($newMolecule) : 'NULL';
1392 global $remote_username;
1393 $comment = empty ($_REQUEST['comment']) ? 'NULL' : "'${_REQUEST['comment']}'";
1394 $query =
1395 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1396 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1397 global $dbxlink;
1398 $result = $dbxlink->query ($query);
1399 if ($result == NULL)
1400 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1401 else
1402 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1403 }
1404 printLog ($log);
1405 }
1406
1407 // This is the time for rendering.
1408 global $root, $pageno, $tabno;
1409 echo "<form id='racks' action='${root}'>";
1410 echo "<input type=hidden name=page value='${pageno}'>\n";
1411 echo "<input type=hidden name=tab value='${tabno}'>\n";
1412 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1413 // Main layout starts.
1414 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1415
1416 // Left portlet with rack list.
1417 echo "<td class=pcleft height='1%'>";
1418 startPortlet ('Racks');
1419 $allRacksData = getRacksForRow();
1420 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1421 {
1422 foreach (array_keys ($allRacksData) as $rack_id)
1423 {
1424 $rackData = getRackData ($rack_id);
1425 if ($rackData == NULL)
1426 {
1427 showError ('getRackData() failed', __FUNCTION__);
1428 return NULL;
1429 }
1430 $workingRacksData[$rack_id] = $rackData;
1431 }
1432 foreach ($workingRacksData as &$rackData)
1433 applyObjectMountMask ($rackData, $object_id);
1434 unset ($rackData);
1435 }
1436 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1437 echo "<br>";
1438 echo "<br>";
1439 finishPortlet();
1440 echo "</td>";
1441
1442 // Middle portlet with comment and submit.
1443 echo "<td class=pcleft>";
1444 startPortlet ('Comment');
1445 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1446 echo "<input type=submit value='Save' name=got_atoms>\n";
1447 echo "<br>";
1448 echo "<br>";
1449 finishPortlet();
1450 echo "</td>";
1451
1452 // Right portlet with rendered racks. If this form submit is not final, we have to
1453 // reflect the former state of the grid in current form.
1454 echo "<td class=pcright rowspan=2 height='1%'>";
1455 startPortlet ('Working copy');
1456 echo '<table border=0 cellspacing=10 align=center><tr>';
1457 foreach ($workingRacksData as $rack_id => $rackData)
1458 {
1459 // Order is important here: only original allocation is highlighted.
1460 highlightObject ($rackData, $object_id);
1461 markupAtomGrid ($rackData, 'T');
1462 // If we have a form processed, discard user input and show new database
1463 // contents.
1464 if (!$is_submit and $is_update)
1465 mergeGridFormToRack ($rackData);
1466 echo "<td valign=top>";
1467 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1468 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1469 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1470 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1471 renderAtomGrid ($rackData);
1472 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1473 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1474 echo "</table></center>\n";
1475 echo '</td>';
1476 }
1477 echo "</tr></table>";
1478 finishPortlet();
1479 echo "</td>\n";
1480
1481 echo "</form>\n";
1482 echo "</tr></table>\n";
1483 }
1484
1485 function renderMolecule ($mdata, $object_id)
1486 {
1487 // sort data out
1488 $rackpack = array();
1489 global $loclist;
1490 foreach ($mdata as $rua)
1491 {
1492 $rack_id = $rua['rack_id'];
1493 $unit_no = $rua['unit_no'];
1494 $atom = $rua['atom'];
1495 if (!isset ($rackpack[$rack_id]))
1496 {
1497 $rackData = getRackData ($rack_id);
1498 for ($i = $rackData['height']; $i > 0; $i--)
1499 for ($locidx = 0; $locidx < 3; $locidx++)
1500 $rackData[$i][$locidx]['state'] = 'F';
1501 $rackpack[$rack_id] = $rackData;
1502 }
1503 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1504 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1505 }
1506 // now we have some racks to render
1507 foreach ($rackpack as $rackData)
1508 {
1509 markAllSpans ($rackData);
1510 echo "<table class=molecule cellspacing=0>\n";
1511 echo "<caption>${rackData['name']}</caption>\n";
1512 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1513 for ($i = $rackData['height']; $i > 0; $i--)
1514 {
1515 echo "<tr><th>$i</th>";
1516 for ($locidx = 0; $locidx < 3; $locidx++)
1517 {
1518 $state = $rackData[$i][$locidx]['state'];
1519 echo "<td class=state_${state}>&nbsp;</td>\n";
1520 }
1521 echo "</tr>\n";
1522 }
1523 echo "</table>\n";
1524 }
1525 }
1526
1527 function renderUnmountedObjectsPortlet ()
1528 {
1529 startPortlet ('Unmounted objects');
1530 $objs = getUnmountedObjects();
1531 if ($objs === NULL)
1532 {
1533 showError ('getUnmountedObjects() failed', __FUNCTION__);
1534 return;
1535 }
1536 global $root, $nextorder;
1537 $order = 'odd';
1538 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1539 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
1540 foreach ($objs as $obj)
1541 {
1542 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1543 echo "<td>${obj['label']}</td>";
1544 echo "<td>${obj['asset_no']}</td>";
1545 echo "<td>${obj['barcode']}</td></tr>";
1546 $order = $nextorder[$order];
1547 }
1548 echo "</table><br>\n";
1549 finishPortlet();
1550 }
1551
1552 function renderProblematicObjectsPortlet ()
1553 {
1554 startPortlet ('Problematic objects');
1555 $objs = getProblematicObjects();
1556 if ($objs === NULL)
1557 {
1558 showError ('getProblematicObjects() failed', __FUNCTION__);
1559 return;
1560 }
1561 global $root, $nextorder;
1562 $order = 'odd';
1563 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1564 echo '<tr><th>Type</th><th>Common name</th></tr>';
1565 foreach ($objs as $obj)
1566 {
1567 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1568 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1569 $order = $nextorder[$order];
1570 }
1571 echo "</table><br>\n";
1572 finishPortlet();
1573 }
1574
1575 function renderObjectSpace ()
1576 {
1577 global $root, $taglist, $tagtree;
1578 echo "<table border=0 class=objectview>\n";
1579 echo "<tr><td class=pcleft width='50%'>";
1580 startPortlet ('View all by type');
1581 $groupInfo = getObjectGroupInfo();
1582 if ($groupInfo === NULL)
1583 {
1584 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1585 return;
1586 }
1587 if (count ($groupInfo) == 0)
1588 echo "No objects exist in DB";
1589 else
1590 {
1591 echo '<div align=left><ul>';
1592 foreach ($groupInfo as $gi)
1593 echo "<li><a href='${root}?page=objgroup&group_id=${gi['id']}'>${gi['name']}</a> (${gi['count']})</li>";
1594 echo '</ul></div>';
1595 }
1596 finishPortlet();
1597
1598 echo '</td><td class=pcright>';
1599
1600 startPortlet ('View all by tag');
1601 if (count ($taglist) == 0)
1602 echo "No tags exist in DB";
1603 else
1604 renderTagCloud ('object');
1605 finishPortlet();
1606 echo "</td></tr></table>\n";
1607 }
1608
1609 function renderObjectGroup ()
1610 {
1611 global $root, $pageno, $tabno, $nextorder, $taglist, $tagtree;
1612 assertUIntArg ('group_id', __FUNCTION__, TRUE);
1613 $group_id = $_REQUEST['group_id'];
1614 $tagfilter = getTagFilter();
1615 $tagfilter_str = getTagFilterStr ($tagfilter);
1616 echo "<table border=0 class=objectview>\n";
1617 echo "<tr><td class=pcleft width='25%'>";
1618 startPortlet ('change type');
1619 $groupInfo = getObjectGroupInfo();
1620 if ($groupInfo === NULL)
1621 {
1622 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1623 return;
1624 }
1625 if (count ($groupInfo) == 0)
1626 echo "No objects exist in DB";
1627 else
1628 {
1629 echo '<div align=left><ul>';
1630 foreach ($groupInfo as $gi)
1631 {
1632 echo "<li><a href='${root}?page=${pageno}&group_id=${gi['id']}${tagfilter_str}'>";
1633 if ($gi['id'] == $group_id)
1634 echo '<strong>';
1635 echo "${gi['name']}</a>";
1636 if ($gi['id'] == $group_id)
1637 echo '</strong>';
1638 echo " (${gi['count']})";
1639 if ($gi['id'] == $group_id)
1640 echo ' &larr;';
1641 echo "</li>";
1642 }
1643 echo '</ul></div>';
1644 }
1645 finishPortlet();
1646
1647 echo '</td><td class=pcleft>';
1648
1649 startPortlet ('Objects');
1650 $objects = getObjectList ($group_id, $tagfilter);
1651 if ($objects === NULL)
1652 {
1653 showError ('getObjectList() failed', __FUNCTION__);
1654 return;
1655 }
1656 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1657 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
1658 $order = 'odd';
1659 foreach ($objects as $obj)
1660 {
1661 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1662 echo "<td>${obj['label']}</td>";
1663 echo "<td>${obj['asset_no']}</td>";
1664 echo "<td>${obj['barcode']}</td>";
1665 if ($obj['rack_id'])
1666 echo "<td><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
1667 else
1668 echo '<td>Unmounted</td>';
1669 echo '</tr>';
1670 $order = $nextorder[$order];
1671 }
1672 echo '</table>';
1673 finishPortlet();
1674
1675 echo "</td><td class=pcright width='25%'>";
1676
1677 renderTagFilterPortlet ($tagfilter, 'object', 'group_id', $group_id);
1678 echo "</td></tr></table>\n";
1679 }
1680
1681 function renderEmptyPortsSelect ($port_id, $type_id)
1682 {
1683 $ports = getEmptyPortsOfType($type_id);
1684 usort($ports, 'sortEmptyPorts');
1685 foreach ($ports as $port)
1686 {
1687 if ($port_id == $port['Port_id'])
1688 continue;
1689 echo "<option value='${port['Port_id']}' onclick='getElementById(\"remote_port_name\").value=\"${port['Port_name']}\"; getElementById(\"remote_object_name\").value=\"${port['Object_name']}\";'>${port['Object_name']} ${port['Port_name']}</option>\n";
1690 }
1691 }
1692
1693 function renderObjectAddressesAndNames ()
1694 {
1695 $addresses = getObjectAddressesAndNames();
1696 usort($addresses, 'sortObjectAddressesAndNames');
1697 foreach ($addresses as $address)
1698 {
1699 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1700 }
1701 }
1702
1703 // History viewer for history-enabled simple dictionaries.
1704 function renderHistory ($object_type, $object_id)
1705 {
1706 switch ($object_type)
1707 {
1708 case 'row':
1709 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1710 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1711 $extra = 4;
1712 break;
1713 case 'rack':
1714 $query =
1715 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1716 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1717 "natural join Chapter " .
1718 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1719 $header = '<tr><th>change time</th><th>author</th><th>rack name</th><th>is deleted?</th><th>rack row name</th><th>rack height</th><th>rack comment</th></tr>';
1720 $extra = 6;
1721 break;
1722 case 'object':
1723 $query =
1724 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1725 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1726 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1727 $header = '<tr><th>change time</th><th>author</th><th>common name</th><th>visible label</th><th>barcode</th><th>asset no</th><th>is deleted?</th><th>has problems?</th><th>object type</th><th>comment</th></tr>';
1728 $extra = 9;
1729 break;
1730 default:
1731 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1732 return;
1733 }
1734 global $dbxlink;
1735 $result = $dbxlink->query ($query);
1736 if ($result == NULL)
1737 {
1738 showError ('SQL query failed', __FUNCTION__);
1739 return;
1740 }
1741 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1742 $order = 'odd';
1743 global $nextorder;
1744 echo $header;
1745 while ($row = $result->fetch (PDO::FETCH_NUM))
1746 {
1747 echo "<tr class=row_${order}><td>${row[0]}</td>";
1748 for ($i = 1; $i <= $extra; $i++)
1749 echo "<td>" . $row[$i] . "</td>";
1750 echo "</tr>\n";
1751 $order = $nextorder[$order];
1752 }
1753 echo "</table><br>\n";
1754 }
1755
1756 function renderRackspaceHistory ()
1757 {
1758 global $root, $nextorder, $pageno, $tabno;
1759 $order = 'odd';
1760 $history = getRackspaceHistory();
1761 // Show the last operation by default.
1762 if (isset ($_REQUEST['op_id']))
1763 $op_id = $_REQUEST['op_id'];
1764 elseif (isset ($history[0]['mo_id']))
1765 $op_id = $history[0]['mo_id'];
1766 else $op_id = NULL;
1767
1768 $omid = NULL;
1769 $nmid = NULL;
1770 $object_id = 1;
1771 if ($op_id)
1772 list ($omid, $nmid) = getOperationMolecules ($op_id);
1773
1774 // Main layout starts.
1775 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1776
1777 // Left top portlet with old allocation.
1778 echo "<tr><td class=pcleft>";
1779 startPortlet ('Old allocation');
1780 if ($omid)
1781 {
1782 $oldMolecule = getMolecule ($omid);
1783 renderMolecule ($oldMolecule, $object_id);
1784 }
1785 else
1786 echo "nothing";
1787 finishPortlet();
1788
1789 echo '</td><td class=pcright>';
1790
1791 // Right top portlet with new allocation
1792 startPortlet ('New allocation');
1793 if ($nmid)
1794 {
1795 $newMolecule = getMolecule ($nmid);
1796 renderMolecule ($newMolecule, $object_id);
1797 }
1798 else
1799 echo "nothing";
1800 finishPortlet();
1801
1802 echo '</td></tr><tr><td colspan=2>';
1803
1804 // Bottom portlet with list
1805
1806 startPortlet ('Rackspace allocation history');
1807 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1808 echo "<tr><th>timestamp</th><th>author</th><th>rack object ID</th><th>rack object type</th><th>rack object name</th><th>comment</th></tr>\n";
1809 foreach ($history as $row)
1810 {
1811 if ($row['mo_id'] == $op_id)
1812 $class = 'hl';
1813 else
1814 $class = "row_${order}";
1815 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1816 echo "<td>${row['user_name']}</td>";
1817 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1818 echo "</tr>\n";
1819 $order = $nextorder[$order];
1820 }
1821 echo "</table>\n";
1822 finishPortlet();
1823
1824 echo '</td></tr></table>';
1825
1826 }
1827
1828 function renderAddressspace ()
1829 {
1830 global $root, $page;
1831
1832 echo "<table border=0 class=objectview>\n";
1833 echo "<tr><td class=pcleft>";
1834
1835 startPortlet ('Subnets');
1836 echo "<table class='widetable' border=0 cellpadding=10 cellspacing=0 align='center'>\n";
1837 $tagfilter = getTagFilter();
1838 $addrspaceList = getAddressspaceList ($tagfilter);
1839 echo "<tr><th>Subnet</th><th>Name</th><th>Utilization</th></tr>";
1840 foreach ($addrspaceList as $iprange)
1841 {
1842 $range = getIPRange ($iprange['id']);
1843 $total = ($iprange['ip_bin'] | $iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin']) + 1;
1844 $used = count ($range['addrlist']);
1845 echo "<tr><td class=tdleft><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td>";
1846 echo "<td class=tdleft>${iprange['name']}</td><td class=tdleft>";
1847 renderProgressBar ($used/$total);
1848 echo " ${used}/${total}</td></tr>";
1849 }
1850 echo "</table>\n";
1851 finishPortlet();
1852 echo '</td><td class=pcright>';
1853 renderTagFilterPortlet ($tagfilter, 'ipv4net');
1854 echo "</td></tr></table>\n";
1855 }
1856
1857 function renderIPv4SLB ()
1858 {
1859 global $root, $page, $nextorder;
1860
1861 startPortlet ('SLB configuration');
1862 echo "<table border=0 width='100%'><tr>";
1863 foreach (array ('vservices', 'rspools', 'rservers', 'lbs') as $pno)
1864 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
1865 echo '</tr></table>';
1866 finishPortlet();
1867
1868 $summary = getSLBSummary();
1869 startPortlet ('SLB tactical overview');
1870 // A single id-keyed array isn't used here to preserve existing
1871 // order of LBs returned by getSLBSummary()
1872 $lblist = array();
1873 $lbdname = array();
1874 foreach ($summary as $vipdata)
1875 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
1876 if (!in_array ($lb_object_id, $lblist))
1877 {
1878 $oi = getObjectInfo ($lb_object_id);
1879 $lbdname[$lb_object_id] = $oi['dname'];
1880 $lblist[] = $lb_object_id;
1881 }
1882 if (!count ($summary))
1883 echo 'none configured';
1884 else
1885 {
1886 $order = 'odd';
1887 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
1888 echo "<tr><th>VS&nbsp;&darr; LB&nbsp;&rarr;</th>";
1889 foreach ($lblist as $lb_object_id)
1890 echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
1891 echo "</tr>\n";
1892 foreach ($summary as $vsid => $vsdata)
1893 {
1894 echo "<tr class=row_${order}><td class=tdleft><a href='$root?page=vservice&tab=default&id=${vsid}'>";
1895 echo buildVServiceName ($vsdata);
1896 echo '</a>';
1897 if (!empty ($vsdata['name']))
1898 echo " (${vsdata['name']})";
1899 echo "</td>";
1900 foreach ($lblist as $lb_object_id)
1901 {
1902 echo '<td class=tdleft>';
1903 if (!isset ($vsdata['lblist'][$lb_object_id]))
1904 echo '&nbsp;';
1905 else
1906 {
1907 echo $vsdata['lblist'][$lb_object_id]['size'];
1908 echo " (<a href='${root}?page=rspool&pool_id=";
1909 echo $vsdata['lblist'][$lb_object_id]['id'] . "'>";
1910 echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
1911 }
1912 echo '</td>';
1913 }
1914 echo "</tr>\n";
1915 $order = $nextorder[$order];
1916 }
1917 echo "</table>\n";
1918 }
1919 finishPortlet ();
1920 }
1921
1922 function renderAddNewRange ()
1923 {
1924 global $root, $pageno, $tabno;
1925 showMessageOrError();
1926
1927 startPortlet ("Add New");
1928 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1929 echo "<tr><th>Address range</th><th>Name</th><th>connected network</th><th>assign tags</th><th>&nbsp;</th></tr>\n";
1930 echo "<form name='add_new_range' action='process.php'>\n";
1931 echo "<input type=hidden name=op value=addRange>\n";
1932 echo "<input type=hidden name=page value='${pageno}'>\n";
1933 echo "<input type=hidden name=tab value='${tabno}'>\n";
1934 echo "<tr valign=top><td class='tdcenter'><input type=text name='range' size=18 class='live-validate' tabindex=1></td>\n";
1935 echo "<td class='tdcenter'><input type=text name='name' size='20' tabindex=2></td>\n";
1936 echo "<td class='tdcenter'><input type=checkbox name='is_bcast' tabindex=3 checked></td>\n";
1937 echo "<td>\n";
1938 renderTagSelect();
1939 echo "</td>\n";
1940 echo "<td class='tdcenter'><input type=submit value='Add a new range' tabindex=4></td>\n";
1941 echo "</td></tr>\n";
1942 echo "</form></table><br><br>\n";
1943 finishPortlet();
1944
1945 startPortlet ("Manage Existing");
1946 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1947 $addrspaceList = getAddressspaceList();
1948 echo "<tr><th>&nbsp;</th><th>Address range</th><th>Name</th><th>Utilization</th></tr>";
1949 foreach ($addrspaceList as $iprange)
1950 {
1951 $range = getIPRange($iprange['id']);
1952 $usedips = count ($range['addrlist']);
1953 $totalips = ($iprange['ip_bin'] | $iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin']) + 1;
1954 echo "<tr><td>";
1955 if ($usedips == 0)
1956 {
1957 echo "<a href='process.php?op=delRange&page=${pageno}&tab=${tabno}&id=${iprange['id']}'>";
1958 printImageHREF ('delete', 'Delete this IP range');
1959 echo "</a>";
1960 }
1961 else
1962 printImageHREF ('nodelete', 'There are IP addresses allocated or reserved');
1963 echo "</td>\n<td class=tdleft><a href='${root}?page=iprange&id=${iprange['id']}'>";
1964 echo "${iprange['ip']}/${iprange['mask']}</a></td><td class=tdleft>${iprange['name']}";
1965 echo "</td><td class=tdleft>";
1966 renderProgressBar ($usedips / $totalips);
1967 echo " ${usedips}/${totalips}";
1968 echo "</td></tr>";
1969 }
1970 echo "</table>";
1971 finishPortlet();
1972 }
1973
1974 function renderIPRange ($id)
1975 {
1976 global $root, $pageno, $tabno;
1977 $netmaskbylen = array
1978 (
1979 32 => '255.255.255.255',
1980 31 => '255.255.255.254',
1981 30 => '255.255.255.252',
1982 29 => '255.255.255.248',
1983 28 => '255.255.255.240',
1984 27 => '255.255.255.224',
1985 26 => '255.255.255.192',
1986 25 => '255.255.255.128',
1987 24 => '255.255.255.0',
1988 23 => '255.255.254.0',
1989 22 => '255.255.252.0',
1990 21 => '255.255.248.0',
1991 20 => '255.255.240.0',
1992 19 => '255.255.224.0',
1993 18 => '255.255.192.0',
1994 17 => '255.255.128.0',
1995 16 => '255.255.0.0',
1996 15 => '255.254.0.0',
1997 14 => '255.252.0.0',
1998 13 => '255.248.0.0',
1999 12 => '255.240.0.0',
2000 11 => '255.224.0.0',
2001 10 => '255.192.0.0',
2002 9 => '255.128.0.0',
2003 8 => '255.0.0.0',
2004 7 => '254.0.0.0',
2005 6 => '252.0.0.0',
2006 5 => '248.0.0.0',
2007 4 => '240.0.0.0',
2008 3 => '224.0.0.0',
2009 2 => '192.0.0.0',
2010 1 => '128.0.0.0'
2011 );
2012 $wildcardbylen = array
2013 (
2014 32 => '0.0.0.0',
2015 31 => '0.0.0.1',
2016 30 => '0.0.0.3',
2017 29 => '0.0.0.7',
2018 28 => '0.0.0.15',
2019 27 => '0.0.0.31',
2020 26 => '0.0.0.63',
2021 25 => '0.0.0.127',
2022 24 => '0.0.0.255',
2023 23 => '0.0.1.255',
2024 22 => '0.0.3.255',
2025 21 => '0.0.7.255',
2026 20 => '0.0.15.255',
2027 19 => '0.0.31.255',
2028 18 => '0.0.63.255',
2029 17 => '0.0.127.255',
2030 16 => '0.0.255.25',
2031 15 => '0.1.255.255',
2032 14 => '0.3.255.255',
2033 13 => '0.7.255.255',
2034 12 => '0.15.255.255',
2035 11 => '0.31.255.255',
2036 10 => '0.63.255.255',
2037 9 => '0.127.255.255',
2038 8 => '0.255.255.255',
2039 7 => '1.255.255.255',
2040 6 => '3.255.255.255',
2041 5 => '7.255.255.255',
2042 4 => '15.255.255.255',
2043 3 => '31.255.255.255',
2044 2 => '63.255.255.255',
2045 1 => '127.255.255.255'
2046 );
2047 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2048 if (isset($_REQUEST['pg']))
2049 $page = $_REQUEST['pg'];
2050 else
2051 $page=0;
2052
2053 $range = getIPRange($id);
2054 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2055 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2056
2057 echo "<tr><td class=pcleft width='50%'>";
2058 startPortlet ('summary');
2059 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2060 $used = count ($range['addrlist']);
2061 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2062 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
2063 renderProgressBar ($used/$total);
2064 echo "&nbsp;${used}/${total}</td></tr>\n";
2065 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2066 echo $netmaskbylen[$range['mask']];
2067 echo "</td></tr>\n";
2068 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2069 echo $wildcardbylen[$range['mask']];
2070 echo "</td></tr>\n";
2071 printTagTRs ("${root}?page=ipv4space&");
2072 echo "</table><br>\n";
2073 finishPortlet();
2074 echo "</td>\n";
2075
2076 echo "<td class=pcright>";
2077 startPortlet ('details');
2078 $startip = $range['ip_bin'] & $range['mask_bin'];
2079 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2080 $realstartip = $startip;
2081 $realendip = $endip;
2082 $numpages = 0;
2083 if($endip - $startip > $maxperpage)
2084 {
2085 $numpages = ($endip - $startip)/$maxperpage;
2086 $startip = $startip + $page * $maxperpage;
2087 $endip = $startip + $maxperpage-1;
2088 }
2089 echo "<center>";
2090 if ($numpages)
2091 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2092 for ($i=0; $i<$numpages; $i++)
2093 {
2094 if ($i == $page)
2095 echo "<b>$i</b> ";
2096 else
2097 echo "<a href='${root}?page=${pageno}&tab=${tabno}&id=$id&pg=$i'>$i</a> ";
2098 }
2099 echo "</center>";
2100
2101 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
2102 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2103
2104
2105 for($ip = $startip; $ip<=$endip; $ip++)
2106 {
2107 if (isset ($range['addrlist'][$ip]))
2108 {
2109 $numshared = countRefsOfType($range['addrlist'][$ip]['references'], 'shared', 'eq');
2110 $numreg = countRefsOfType($range['addrlist'][$ip]['references'], 'regular', 'eq');
2111 $numvirt = countRefsOfType($range['addrlist'][$ip]['references'], 'virtual', 'eq');
2112 $numlb = count ($range['addrlist'][$ip]['lbrefs']);
2113 $numrs = count ($range['addrlist'][$ip]['rsrefs']);
2114
2115 $addr = $range['addrlist'][$ip];
2116 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
2117 echo "<tr class='trerror'>";
2118 elseif ( $addr['reserved'] == 'yes' and $numshared+$numreg+$numvirt+$numlb+$numrs > 0)
2119 echo "<tr class='trerror'>";
2120 elseif ( $addr['reserved'] == 'yes')
2121 echo "<tr class='trbusy'>";
2122 elseif ( $numshared > 0 || $numreg > 0 || $numlb > 0 || $numrs > 0)
2123 echo "<tr class='trbusy'>";
2124 else
2125 echo "<tr>";
2126
2127 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
2128 echo "<td class=tdleft>${addr['name']}</td><td class=tdleft>";
2129 $delim = '';
2130 $prologue = '';
2131 if ( $addr['reserved'] == 'yes')
2132 {
2133 echo "<b>Reserved</b> ";
2134 $delim = '; ';
2135 }
2136 foreach ($range['addrlist'][$ip]['references'] as $ref)
2137 {
2138 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}'>";
2139 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2140 echo "${ref['object_name']}</a>";
2141 $delim = '; ';
2142 }
2143 if ($delim != '')
2144 {
2145 $delim = '';
2146 $prologue = '<br>';
2147 }
2148 foreach ($range['addrlist'][$ip]['lbrefs'] as $ref)
2149 {
2150 echo $prologue;
2151 $prologue = '';
2152 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}'>";
2153 echo "${ref['object_name']}</a>:<a href='${root}?page=vservice&id=${ref['vs_id']}'>";
2154 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2155 $delim = '; ';
2156 }
2157 if ($delim != '')
2158 {
2159 $delim = '';
2160 $prologue = '<br>';
2161 }
2162 foreach ($range['addrlist'][$ip]['rsrefs'] as $ref)
2163 {
2164 echo $prologue;
2165 $prologue = '';
2166 echo "${delim}&rarr;${ref['rsport']}@<a href='${root}?page=rspool&pool_id=${ref['rspool_id']}'>";
2167 echo "${ref['rspool_name']}</a>";
2168 $delim = '; ';
2169 }
2170 echo "</td></tr>\n";
2171 }
2172 else
2173 {
2174 echo "<tr><td><a href='${root}?page=ipaddress&ip=".long2ip($ip)."'>".long2ip($ip)."</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
2175 }
2176 }
2177
2178 echo "</table>";
2179 finishPortlet();
2180 echo "</td></tr></table>\n";
2181 }
2182
2183 function renderIPRangeProperties ($id)
2184 {
2185 global $pageno, $tabno;
2186 showMessageOrError();
2187 $range = getIPRange($id);
2188 echo "<center><h1>${range['ip']}/${range['mask']}</h1></center>\n";
2189 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2190 echo "<form action='process.php'><input type=hidden name=op value=editRange>";
2191 echo "<input type=hidden name=page value='${pageno}'>\n";
2192 echo "<input type=hidden name=tab value='${tabno}'>\n";
2193 echo "<input type=hidden name=id value='${id}'>";
2194 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${range['name']}'></tr><tr><td colspan=2 class='tdcenter'><input type=submit value='Update range'></td></form></tr>";
2195 echo "</table>\n";
2196
2197 }
2198
2199 function renderIPAddress ()
2200 {
2201 global $root;
2202 $ip = $_REQUEST['ip'];
2203 $address = getIPAddress($ip);
2204 echo "<center><h1>$ip</h1>";
2205 if ($address['exists'] == 1)
2206 echo "<h2>${address['name']}</h2>";
2207 echo "</center>\n";
2208
2209 // echo "<table width='100%' cesspadding=5 cellspacing=0 border=0 align='center'>";
2210 // echo "<tr valign='top'><td>";
2211
2212 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
2213 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
2214 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
2215
2216 if ($address['reserved'] == 'yes' or ($numshared + $numreg + $numvirt) > 0)
2217 {
2218 startPortlet ('Allocation');
2219 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2220 echo "<tr><th>Object name</th><th>Interface name</th><th>Interface type</th></tr>\n";
2221 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
2222 $class='trerror';
2223 elseif ( $address['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
2224 $class='trerror';
2225 else
2226 $class='';
2227
2228 if ($address['reserved'] == 'yes')
2229 echo "<tr class='$class'><td colspan='3'><b>RESERVED</b></td></tr>";
2230 foreach ($address['bonds'] as $bond)
2231 {
2232 echo "<tr class='$class'><td><a href='${root}?page=object&object_id=${bond['object_id']}'>${bond['object_name']}</td><td>${bond['name']}</td><td><b>";
2233 switch ($bond['type'])
2234 {
2235 case 'virtual':
2236 echo "Virtual";
2237 break;
2238 case 'shared':
2239 echo "Shared";
2240 break;
2241 case 'regular':
2242 echo "Regular";
2243 break;
2244 }
2245 echo "</b></td></tr>\n";
2246 }
2247 echo "</table><br><br>";
2248 finishPortlet();
2249 }
2250
2251 if (count ($address['vslist']))
2252 {
2253 startPortlet ('Virtual services (' . count ($address['vslist']) . ')');
2254 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2255 echo "<tr><th>VS</th><th>name</th></tr>\n";
2256 foreach ($address['vslist'] as $vsinfo)
2257 {
2258 echo "<tr><td class=tdleft><a href='${root}?page=vservice&id=${vsinfo['id']}'>";
2259 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2260 echo $vsinfo['name'] . "</td></tr>\n";
2261 }
2262 echo "</table><br><br>";
2263 finishPortlet();
2264 }
2265
2266 if (count ($address['rslist']))
2267 {
2268 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2269 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2270 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2271 foreach ($address['rslist'] as $rsinfo)
2272 {
2273 echo "<tr><td>";
2274 if ($rsinfo['inservice'] == 'yes')
2275 printImageHREF ('inservice', 'in service');
2276 else
2277 printImageHREF ('notinservice', 'NOT in service');
2278 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='${root}?page=rspool&pool_id=${rsinfo['pool_id']}'>";
2279 echo $rsinfo['poolname'] . "</a></td></tr>\n";
2280 }
2281 echo "</table><br><br>";
2282 finishPortlet();
2283 }
2284
2285
2286 // echo "</td><td>";
2287 // echo "</td></tr></table>";
2288 }
2289
2290 function renderIPAddressProperties ()
2291 {
2292 global $pageno, $tabno;
2293 $ip = $_REQUEST['ip'];
2294 showMessageOrError();
2295 $address = getIPAddress($ip);
2296 echo "<center><h1>$ip</h1></center>\n";
2297 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2298 echo "<form action='process.php'><input type=hidden name=op value=editAddress>";
2299 echo "<input type=hidden name=page value='${pageno}'>\n";
2300 echo "<input type=hidden name=tab value='${tabno}'>\n";
2301 echo "<input type=hidden name=ip value='${ip}'>";
2302 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='".($address['exists']==1?$address['name']:'')."'></tr>";
2303 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ".($address['exists']==1?(($address['reserved']=='yes')?'checked':''):'')."></tr>";
2304 echo "<tr><td colspan=2 class='tdcenter'><input type=submit value='Update address'></td></form></tr>";
2305 echo "</table>\n";
2306
2307 }
2308
2309 function renderIPAddressAssignment ()
2310 {
2311 global $pageno, $tabno, $root;
2312 $ip = $_REQUEST['ip'];
2313 $address = getIPAddress($ip);
2314
2315 showMessageOrError();
2316 echo "<center><h1>$ip</h1></center>\n";
2317
2318
2319 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2320 echo "<tr><th>&nbsp;</th><th>Object name</th><th>Interface name</th><th>Interface type</th><th>&nbsp;</th></tr>\n";
2321
2322 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
2323 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
2324 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
2325
2326
2327 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
2328 $class='trerror';
2329 elseif ( $address['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
2330 $class='trerror';
2331 else
2332 $class='';
2333
2334
2335
2336 if ($address['reserved'] == 'yes')
2337 echo "<tr class='$class'><td colspan='5'><b>RESERVED</b></td></tr>";
2338 foreach ($address['bonds'] as $bond)
2339 {
2340 echo "<tr class='$class'><form action='process.php'>";
2341 echo "<input type=hidden name=op value='editBondForAddress'>";
2342 echo "<input type=hidden name=page value='${pageno}'>";
2343 echo "<input type=hidden name=tab value='${tabno}'>";
2344 echo "<input type=hidden name=ip value='$ip'>";
2345 echo "<input type=hidden name=object_id value='${bond['object_id']}'>";
2346 echo "<td><a href='process.php?op=delIpAssignment&page=${pageno}&tab=${tabno}&ip=$ip&object_id=${bond['object_id']}'>";
2347 printImageHREF ('delete', 'Unallocate address');
2348 echo "</a></td>";
2349 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}'>${bond['object_name']}</td>";
2350 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td>";
2351 echo "<td><select name='bond_type'>";
2352 switch ($bond['type'])
2353 {
2354 case 'virtual':
2355 echo "<option value='regular'>Regular</option>";
2356 echo "<option value='virtual' selected>Virtual</option>";
2357 echo "<option value='shared'>Shared</option>";
2358 break;
2359 case 'shared':
2360 echo "<option value='regular'>Regular</option>";
2361 echo "<option value='virtual'>Virtual</option>";
2362 echo "<option value='shared' selected>Shared</option>";
2363 break;
2364 case 'regular':
2365 echo "<option value='regular' selected>Regular</option>";
2366 echo "<option value='virtual'>Virtual</option>";
2367 echo "<option value='shared'>Shared</option>";
2368 break;
2369 }
2370 echo "</select></td><td><input type='submit' value='OK'></td></form></tr>\n";
2371 }
2372 echo "<form action='process.php'><input type='hidden' name='op' value='bindObjectToIp'>";
2373 echo "<input type=hidden name=page value='${pageno}'>\n";
2374 echo "<input type=hidden name=tab value='${tabno}'>\n";
2375 echo "<input type='hidden' name='ip' value='$ip'>";
2376 echo "<td colspan=2><select name='object_id'>";
2377
2378 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
2379 foreach (getObjectList ($type) as $object)
2380 echo "<option value='${object['id']}'>${object['dname']}</option>";
2381
2382 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td>";
2383 echo "<td><select name='bond_type'><option value='regular'>Regular</option><option value='virtual'>Virtual</option><option value='shared'>Shared</option></select></td>";
2384 echo "<td><input type='submit' value='Assign address'></td></form></tr>";
2385 echo "</table><br><br>";
2386
2387 }
2388
2389 function renderNATv4ForObject ($object_id = 0)
2390 {
2391 global $pageno, $tabno, $root;
2392
2393 $info = getObjectInfo ($object_id);
2394 $forwards = getNATv4ForObject ($object_id);
2395 $addresses = getObjectAddresses ($object_id);
2396 showMessageOrError();
2397 echo "<center><h2>locally performed NAT</h2></center>";
2398
2399 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2400 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2401
2402 foreach ($forwards['out'] as $pf)
2403 {
2404 $class='trerror';
2405 $name='';
2406 foreach ($addresses as $addr)
2407 if ($addr['ip'] == $pf['localip'])
2408 {
2409 $class='';
2410 $name = $addr['name'];
2411 break;
2412 }
2413
2414 echo "<tr class='$class'>";
2415 echo "<td><a href='process.php?op=delPortForwarding&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto']}&object_id=$object_id&page=${pageno}&tab=${tabno}'>";
2416 printImageHREF ('delete', 'Delete NAT rule');
2417 echo "</a></td>";
2418 echo "<td>${pf['proto']}/${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
2419 if (!empty ($pf['local_addr_name']))
2420 echo ' (' . $pf['local_addr_name'] . ')';
2421 echo "</td>";
2422 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2423
2424 $address=getIPAddress($pf['remoteip']);
2425
2426 echo "<td class='description'>";
2427 if (count ($address['bonds']))
2428 foreach($address['bonds'] as $bond)
2429 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2430 elseif (!empty ($pf['remote_addr_name']))
2431 echo '(' . $pf['remote_addr_name'] . ')';
2432 echo "</td><form action='process.php'><input type='hidden' name='op' value='updPortForwarding'><input type=hidden name=page value='${pageno}'>";
2433 echo "<input type=hidden name=tab value='${tabno}'><input type='hidden' name='object_id' value='$object_id'>";
2434 echo "<input type='hidden' name='localip' value='${pf['localip']}'><input type='hidden' name='localport' value='${pf['localport']}'>";
2435 echo "<input type='hidden' name='remoteip' value='${pf['remoteip']}'><input type='hidden' name='remoteport' value='${pf['remoteport']}'>";
2436 echo "<input type='hidden' name='proto' value='${pf['proto']}'><td class='description'>";
2437 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2438 printImageHREF ('save', 'Save changes', TRUE);
2439 echo "</td></form></tr>";
2440 }
2441 echo "<form action='process.php'><input type='hidden' name='op' value='forwardPorts'>";
2442 echo "<input type='hidden' name='object_id' value='$object_id'>";
2443 echo "<input type=hidden name=page value='${pageno}'>\n";
2444 echo "<input type=hidden name=tab value='${tabno}'>\n";
2445 echo "<tr align='center'><td>";
2446 printImageHREF ('add', 'Add new NAT rule', TRUE);
2447 echo '</td><td>';
2448 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2449 echo "<select name='localip' tabindex=1>";
2450
2451 foreach ($addresses as $addr)
2452 echo "<option value='${addr['ip']}'>" . (empty ($addr['name']) ? '' : "${addr['name']}: ") .
2453 "${addr['ip']}" . (empty ($addr['address_name']) ? '' : " (${addr['address_name']})") . "</option>";
2454
2455 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2456 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2457 echo "<a href='javascript:;' onclick='window.open(\"${root}/find_object_ip_helper.php\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2458 printImageHREF ('find', 'Find object');
2459 echo "</a>";
2460 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2461 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>&nbsp;</td></tr>";
2462 echo "</form>";
2463
2464 echo "</table><br><br>";
2465
2466 echo "<center><h2>arriving NAT connections</h2></center>";
2467 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2468 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2469
2470 foreach ($forwards['in'] as $pf)
2471 {
2472 echo "<tr><td><a href='process.php?op=delPortForwarding&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto']}&object_id=${pf['object_id']}&page=${pageno}&tab=${tabno}'>";
2473 printImageHREF ('delete', 'Delete NAT rule');
2474 echo "</a></td>";
2475 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2476 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2477 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2478 echo "<td class='description'>${pf['description']}</td></tr>";
2479 }
2480
2481 echo "</table><br><br>";
2482 }
2483
2484
2485 function renderAddMultipleObjectsForm ()
2486 {
2487 global $root, $pageno, $tabno, $nextorder;
2488
2489 $type_id = array();
2490 $global_type_id = 0;
2491 $name = array();
2492 $asset_no = array();
2493 $keepvalues = FALSE;
2494 $log = array();
2495 // Look for current submit.
2496 if (isset ($_REQUEST['got_fast_data']))
2497 {
2498 $keepvalues = TRUE;
2499 $max = getConfigVar ('MASSCOUNT');
2500 for ($i = 0; $i < $max; $i++)
2501 {
2502 if (!isset ($_REQUEST["${i}_object_type_id"]))
2503 {
2504 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i + 1);
2505 break;
2506 }
2507 assertUIntArg ("${i}_object_type_id", __FUNCTION__, TRUE);
2508 assertStringArg ("${i}_object_name", __FUNCTION__, TRUE);
2509 assertStringArg ("${i}_object_label", __FUNCTION__, TRUE);
2510 assertStringArg ("${i}_object_asset_no", __FUNCTION__, TRUE);
2511 assertStringArg ("${i}_object_barcode", __FUNCTION__, TRUE);
2512 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2513 // Save user input for possible rendering.
2514 $name[$i] = $_REQUEST["${i}_object_name"];
2515 $label[$i] = $_REQUEST["${i}_object_label"];
2516 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2517 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2518
2519 // It's better to skip silently than printing a notice.
2520 if ($type_id[$i] == 0)
2521 continue;
2522 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i]) === TRUE)
2523 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2524 else
2525 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
2526 }
2527 }
2528 elseif (isset ($_REQUEST['got_very_fast_data']))
2529 {
2530 $keepvalues = TRUE;
2531 assertUIntArg ('global_type_id', __FUNCTION__, TRUE);
2532 assertStringArg ('namelist', __FUNCTION__, TRUE);
2533 $global_type_id = $_REQUEST['global_type_id'];
2534 if ($global_type_id == 0)
2535 {
2536 if (!empty ($_REQUEST['namelist']))
2537 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2538 else
2539 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2540 }
2541 else
2542 {
2543 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2544 $names1 = explode ('\n', $_REQUEST['namelist']);
2545 $names2 = array();
2546 foreach ($names1 as $line)
2547 {
2548 $parts = explode ('\r', $line);
2549 reset ($parts);
2550 if (empty ($parts[0]))
2551 continue;
2552 else
2553 $names2[] = rtrim ($parts[0]);
2554 }
2555 foreach ($names2 as $cname)
2556 if (commitAddObject ($cname, '', '', $global_type_id, '') === TRUE)
2557 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2558 else
2559 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2560 }
2561 }
2562 printLog ($log);
2563
2564 // Render a form for the next.
2565 $typelist = getObjectTypeList();
2566 $typelist[0] = 'select type...';
2567
2568 startPortlet ('Fast way');
2569 echo "<form name=fastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2570 echo '<table border=0 align=center>';
2571 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th></tr>\n";
2572 // If a user forgot to select object type on input, we keep his
2573 // previous input in the form.
2574 $max = getConfigVar ('MASSCOUNT');
2575 for ($i = 0; $i < $max; $i++)
2576 {
2577 echo '<tr><td>';
2578 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2579 printSelect ($typelist, "${i}_object_type_id", 0);
2580 echo '</td>';
2581 echo "<td><input type=text size=30 name=${i}_object_name";
2582 if ($keepvalues and $type_id[$i] == 0)
2583 echo " value='${name[$i]}'";
2584 echo "></td>";
2585 echo "<td><input type=text size=30 name=${i}_object_label";
2586 if ($keepvalues and $type_id[$i] == 0)
2587 echo " value='${label[$i]}'";
2588 echo "></td>";
2589 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2590 if ($keepvalues and $type_id[$i] == 0)
2591 echo " value='${asset_no[$i]}'";
2592 echo "></td>";
2593 echo "<td><input type=text size=10 name=${i}_object_barcode";
2594 if ($keepvalues and $type_id[$i] == 0)
2595 echo " value='${barcode[$i]}'";
2596 echo "></td>";
2597 echo "</tr>\n";
2598 }
2599 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Create'></td></tr>\n";
2600 echo "</form></table>\n";
2601 finishPortlet();
2602
2603 startPortlet ('Very fast way');
2604 echo "<form name=veryfastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2605 echo 'For each line shown below create an object of type ';
2606 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2607 echo " <input type=submit name=got_very_fast_data value='Go!'><br>\n";
2608 echo "<textarea name=namelist cols=40 rows=25>\n";
2609 if ($keepvalues and $global_type_id == 0)
2610 echo $_REQUEST['namelist'];
2611 echo "</textarea></form>\n";
2612 finishPortlet();
2613 }
2614
2615 function printGreeting ()
2616 {
2617 global $remote_username, $accounts, $root;
2618 $account = $accounts[$remote_username];
2619 echo "Hello, ${account['user_realname']}. This is RackTables " . CODE_VERSION . ". Click <a href='${root}?logout'>here</a> to logout.";
2620 }
2621
2622 function renderSearchResults ()
2623 {
2624 global $remote_username, $root;
2625 $terms = trim ($_REQUEST['q']);
2626 if (empty ($terms))
2627 {
2628 showError ('Search string cannot be empty.', __FUNCTION__);
2629 return;
2630 }
2631 if (!authorized ($remote_username, 'object', 'default'))
2632 {
2633 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
2634 return;
2635 }
2636 $nhits = 0;
2637 // If we search for L2 address, we can either find one or find none.
2638 if
2639 (
2640 preg_match ('/^[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?:[0-9a-f][0-9a-f]?$/i', $terms) or
2641 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms) or
2642 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms) or
2643 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2644 preg_match ('/^[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]$/i', $terms)
2645 )
2646 // Search for L2 address.
2647 {
2648 $terms = str_replace ('.', '', $terms);
2649 $terms = str_replace (':', '', $terms);
2650 $terms = substr ($terms, -12);
2651 $result = searchByl2address ($terms);
2652 if ($result !== NULL)
2653 {
2654 $nhits++;
2655 $lasthit = 'port';
2656 $summary['port'][] = $result;
2657 }
2658 }
2659 elseif (preg_match ('/^[0-9][0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9]?[0-9]?[0-9]?$/i', $terms))
2660 // Search for IP address.
2661 {
2662 $result = getRangeByIp ($terms);
2663 if ($result !== NULL)
2664 {
2665 $nhits++;
2666 $lasthit = 'ipv4address1';
2667 $summary['ipv4address1'][] = $terms;
2668 }
2669 }
2670 else
2671 // Search for objects, addresses, networks, virtual services and RS pools by their description.
2672 {
2673 $tmp = getObjectSearchResults ($terms);
2674 if (count ($tmp))
2675 {
2676 $nhits += count ($tmp);
2677 $lasthit = 'object';
2678 $summary['object'] = $tmp;
2679 }
2680 $tmp = getIPv4AddressSearchResult ($terms);
2681 if (count ($tmp))
2682 {
2683 $nhits += count ($tmp);
2684 $lasthit = 'ipv4address2';
2685 $summary['ipv4address2'] = $tmp;
2686 }
2687 $tmp = getIPv4PrefixSearchResult ($terms);
2688 if (count ($tmp))
2689 {
2690 $nhits += count ($tmp);
2691 $lasthit = 'ipv4network';
2692 $summary['ipv4network'] = $tmp;
2693 }
2694 $tmp = getIPv4RSPoolSearchResult ($terms);
2695 if (count ($tmp))
2696 {
2697 $nhits += count ($tmp);
2698 $lasthit = 'ipv4rspool';
2699 $summary['ipv4rspool'] = $tmp;
2700 }
2701 $tmp = getIPv4VServiceSearchResult ($terms);
2702 if (count ($tmp))
2703 {
2704 $nhits += count ($tmp);
2705 $lasthit = 'ipv4vs';
2706 $summary['ipv4vs'] = $tmp;
2707 }
2708 }
2709 if ($nhits == 0)
2710 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2711 elseif ($nhits == 1)
2712 {
2713 $record = current ($summary[$lasthit]);
2714 switch ($lasthit)
2715 {
2716 case 'port':
2717 echo "<script language='Javascript'>document.location='${root}?page=object";
2718 echo "&hl_port_id=" . $record['port_id'];
2719 echo "&object_id=" . $record['object_id'] . "';//</script>";
2720 break;
2721 case 'ipv4address1':
2722 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2723 echo "&ip=${record}";
2724 echo "';//</script>";
2725 break;
2726 case 'ipv4address2':
2727 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2728 echo "&ip=${record['ip']}";
2729 echo "';//</script>";
2730 break;
2731 case 'ipv4network':
2732 echo "<script language='Javascript'>document.location='${root}?page=iprange";
2733 echo "&id=${record['id']}";
2734 echo "';//</script>";
2735 break;
2736 case 'object':
2737 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2738 break;
2739 case 'ipv4rspool':
2740 echo "<script language='Javascript'>document.location='${root}?page=rspool&pool_id=${record['pool_id']}';//</script>";
2741 break;
2742 case 'ipv4vs':
2743 echo "<script language='Javascript'>document.location='${root}?page=vservice&id=${record['id']}';//</script>";
2744 break;
2745 }
2746 return;
2747 }
2748 else
2749 {
2750 global $nextorder;
2751 $order = 'odd';
2752 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
2753 foreach ($summary as $where => $what)
2754 switch ($where)
2755 {
2756 case 'object':
2757 startPortlet ("<a href='${root}?page=objects'>Objects</a>");
2758 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2759 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2760 foreach ($what as $obj)
2761 {
2762 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2763 echo "<td>${obj['label']}</td>";
2764 echo "<td>${obj['asset_no']}</td>";
2765 echo "<td>${obj['barcode']}</td></tr>";
2766 $order = $nextorder[$order];
2767 }
2768 echo '</table>';
2769 finishPortlet();
2770 break;
2771 case 'ipv4network':
2772 startPortlet ("<a href='${root}?page=ipv4space'>IPv4 networks</a>");
2773 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2774 echo '<tr><th>Network</th><th>Descritpion</th></tr>';
2775 foreach ($what as $net)
2776 {
2777 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=iprange&id=${net['id']}'>${net['ip']}";
2778 echo '/' . $net['mask'] . '</a></td>';
2779 echo "<td class=tdleft>${net['name']}</td></tr>";
2780 $order = $nextorder[$order];
2781 }
2782 echo '</table>';
2783 finishPortlet();
2784 break;
2785 case 'ipv4address2':
2786 startPortlet ('IPv4 addresses');
2787 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2788 echo '<tr><th>Address</th><th>Descritpion</th></tr>';
2789 foreach ($what as $addr)
2790 {
2791 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>";
2792 echo "${addr['ip']}</a></td>";
2793 echo "<td class=tdleft>${addr['name']}</td></tr>";
2794 $order = $nextorder[$order];
2795 }
2796 echo '</table>';
2797 finishPortlet();
2798 break;
2799 case 'ipv4rspool':
2800 startPortlet ("<a href='${root}?page=rspools'>RS pools</a>");
2801 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2802 foreach ($what as $rspool)
2803 {
2804 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=rspool&pool_id=${rspool['pool_id']}'>";
2805 echo buildRSPoolName ($rspool);
2806 echo "</a></td></tr>";
2807 $order = $nextorder[$order];
2808 }
2809 echo '</table>';
2810 finishPortlet();
2811 break;
2812 case 'ipv4vs':
2813 startPortlet ("<a href='${root}?page=vservices'>Virtual services</a>");
2814 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2815 echo '<tr><th>VS</th><th>Descritpion</th></tr>';
2816 foreach ($what as $vs)
2817 {
2818 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=vservice&id=${vs['id']}'>";
2819 echo buildVServiceName ($vs);
2820 echo "</a></td><td>${vs['name']}</td></tr>";
2821 $order = $nextorder[$order];
2822 }
2823 echo '</table>';
2824 finishPortlet();
2825 break;
2826 }
2827 }
2828 }
2829
2830 // This function prints a table of checkboxes to aid the user in toggling mount atoms
2831 // from one state to another. The first argument is rack data as
2832 // produced by getRackData(), the second is the value used for the 'unckecked' state
2833 // and the third is the value used for 'checked' state.
2834 // Usage contexts:
2835 // for mounting an object: printAtomGrid ($data, 'F', 'T')
2836 // for changing rack design: printAtomGrid ($data, 'A', 'F')
2837 // for adding rack problem: printAtomGrid ($data, 'F', 'U')
2838 // for adding object problem: printAtomGrid ($data, 'T', 'W')
2839
2840 function renderAtomGrid ($data)
2841 {
2842 $rack_id = $data['id'];
2843 for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
2844 {
2845 echo "<tr><th>${unit_no}</th>";
2846 for ($locidx = 0; $locidx < 3; $locidx++)
2847 {
2848 $state = $data[$unit_no][$locidx]['state'];
2849 echo "<td class=state_${state}";
2850 if (isset ($data[$unit_no][$locidx]['hl']))
2851 echo $data[$unit_no][$locidx]['hl'];
2852 echo ">";
2853 if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
2854 echo '<input type=checkbox disabled>';
2855 else
2856 echo "<input type=checkbox" . $data[$unit_no][$locidx]['checked'] . " name=atom_${rack_id}_${unit_no}_${locidx}>";
2857 echo '</td>';
2858 }
2859 echo "</tr>\n";
2860 }
2861 }
2862
2863 function renderPermissions ()
2864 {
2865 startPortlet ('User permissions');
2866 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2867 echo "<tr><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>";
2868 global $perms, $nextorder;
2869 $order = 'odd';
2870 foreach ($perms as $username => $pages)
2871 foreach ($pages as $page => $tabs)
2872 foreach ($tabs as $tab => $access)
2873 {
2874 echo "<tr class=row_${order}><td class=tdleft>$username</td><td>$page</td><td>$tab</td><td>$access</td></tr>\n";
2875 $order = $nextorder[$order];
2876 }
2877 echo "</table>\n";
2878 finishPortlet();
2879 }
2880
2881 function renderAccounts ()
2882 {
2883 global $nextorder, $accounts;
2884 startPortlet ('User accounts');
2885 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2886 echo "<tr><th class=tdleft>Username</th><th class=tdleft>Real name</th></tr>";
2887 $order = 'odd';
2888 foreach ($accounts as $user)
2889 {
2890 echo "<tr class=row_${order}><td class=tdleft><div title='\$userid_${user['user_id']}'>";
2891 echo "${user['user_name']}</div></td>";
2892 echo "<td class=tdleft>${user['user_realname']}</td></li>";
2893 $order = $nextorder[$order];
2894 }
2895 echo '</table>';
2896 finishPortlet();
2897 }
2898
2899 function renderAccountsEditForm ()
2900 {
2901 global $root, $pageno, $tabno, $accounts;
2902 startPortlet ('User accounts');
2903 showMessageOrError();
2904 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2905 echo "<tr><th>status (click to change)</th><th>Username</th><th>Real name</th><th>Password</th><th>&nbsp;</th></tr>\n";
2906 foreach ($accounts as $account)
2907 {
2908 echo "<form action='${root}process.php'>";
2909 echo "<input type=hidden name=op value=updateAccount>";
2910 echo "<input type=hidden name=page value='${pageno}'>\n";
2911 echo "<input type=hidden name=tab value='${tabno}'>\n";
2912 echo "<input type=hidden name=id value='${account['user_id']}'><tr>";
2913 echo "<td>";
2914 if ($account['user_enabled'] == 'yes' && $account['user_id'] != 1)
2915 {
2916 echo "<a href='${root}process.php?op=disableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2917 printImageHREF ('blockuser', 'disable account');
2918 echo "</a>\n";
2919 }
2920 if ($account['user_enabled'] == 'no' && $account['user_id'] != 1)
2921 {
2922 echo "<a href='${root}process.php?op=enableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2923 printImageHREF ('unblockuser', 'enable account');
2924 echo "</a>\n";
2925 }
2926 // Otherwise skip icon.
2927 echo "</td>";
2928 echo "<td><input type=text name=username value='${account['user_name']}' size=16></td>";
2929 echo "<td><input type=text name=realname value='${account['user_realname']}' size=24></td>";
2930 echo "<td><input type=password name=password value='${account['user_password_hash']}' size=64></td><td>";
2931 printImageHREF ('save', 'Save changes', TRUE);
2932 echo "</td></form></tr>\n";
2933 }
2934 echo "<form action='${root}process.php' method=post><tr>";
2935 echo "<input type=hidden name=op value=createAccount>\n";
2936 echo "<input type=hidden name=page value='${pageno}'>\n";
2937 echo "<input type=hidden name=tab value='${tabno}'>\n";
2938 echo "<td>&nbsp;</td><td><input type=text size=16 name=username tabindex=100></td>\n";
2939 echo "<td><input type=text size=24 name=realname tabindex=101></td>";
2940 echo "<td><input type=password size=64 name=password tabindex=102></td><td>";
2941 printImageHREF ('create', 'Add new account', TRUE, 103);
2942 echo "</td></tr></form>";
2943 echo "</table><br>\n";
2944 finishPortlet();
2945 }
2946
2947 function printChildrenAsOptions ($root, $depth = 0)
2948 {
2949 echo "<option value=${root['title']}>";
2950 if ($depth == 0)
2951 echo '* ';
2952 for ($i = 0; $i < $depth; $i++)
2953 echo '-- ';
2954 echo $root['title'];
2955 echo "</option>\n";
2956 foreach ($root['kids'] as $kid)
2957 printChildrenAsOptions ($kid, $depth + 1);
2958 }
2959
2960 // 1. Find all parentless pages.
2961 // 2. For each of them recursively find all children.
2962 // 3. Output the tree with recursion tree display.
2963 function printPagesTree ()
2964 {
2965 global $page;
2966 echo '<pre>';
2967 foreach ($page as $ctitle => $cpage)
2968 if (!isset ($cpage['parent']))
2969 {
2970 $croot['title'] = $ctitle;
2971 $croot['kids'] = getAllChildPages ($ctitle);
2972 printChildrenAsOptions ($croot);
2973 }
2974 echo '</pre>';
2975 }
2976
2977 function renderPermissionsEditForm ()
2978 {
2979 global $root, $pageno, $tabno, $perms, $accounts;
2980 startPortlet ('User permissions');
2981 showMessageOrError();
2982 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
2983 echo "<tr><th>&nbsp;</th><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>\n";
2984 foreach ($perms as $username => $pages)
2985 foreach ($pages as $access_page => $tabs)
2986 foreach ($tabs as $access_tab => $access)
2987 {
2988 echo "<td>";
2989 if ($username != '%')
2990 $userid = $accounts[$username]['user_id'];
2991 else
2992 $userid = 0;
2993 echo "<a href='${root}process.php?op=revoke&page=${pageno}&tab=${tabno}&access_userid=${userid}&access_page=${access_page}&access_tab=${access_tab}'>";
2994 printImageHREF ('revoke', 'Revoke permission');
2995 echo "</a></td>";
2996 echo "<td>${username}</td>";
2997 echo "<td>${access_page}</td>";
2998 echo "<td>${access_tab}</td>";
2999 echo "<td>${access}</td>";
3000 echo "</tr>\n";
3001 }
3002 echo "<form action='${root}process.php' method=post><tr>";
3003 echo "<input type=hidden name=op value=grant>\n";
3004 echo "<input type=hidden name=page value='${pageno}'>\n";
3005 echo "<input type=hidden name=tab value='${tabno}'>\n";
3006 // FIXME: border=0 doesn't work here for unknown reason
3007 echo "<td>";
3008 printImageHREF ('grant', '', TRUE, 103);
3009 echo "</td>";
3010 echo "<td><select name=access_userid>";
3011 echo "<option value=0>ANY</option>";
3012 foreach ($accounts as $account)
3013 echo "<option value=${account['user_id']}>${account['user_name']}</option>";
3014 echo "</select></td>\n";
3015 echo "<td><select name=access_page>";
3016 echo "<option value='%'>ANY</option>";
3017 printPagesTree();
3018 echo "</select></td>";
3019 echo "<td><input type=text size=16 name=access_tab tabindex=102 value=default></td>";
3020 echo "<td><input type=radio name=access_value value=no checked>no <input type=radio name=access_value value=yes>yes</td>";
3021 echo "</tr></form>";
3022 echo "</table><br>\n";
3023 finishPortlet();
3024 }
3025
3026 function renderPortMapViewer ()
3027 {
3028 renderPortMap (FALSE);
3029 }
3030
3031 function renderPortMapEditor ()
3032 {
3033 renderPortMap (TRUE);
3034 }
3035
3036 function renderPortMap ($editable = FALSE)
3037 {
3038 global $nextorder, $root, $pageno, $tabno;
3039 showMessageOrError();
3040 startPortlet ("Port compatibility map");
3041 $ptlist = getPortTypes();
3042 $pclist = getPortCompat();
3043 $pctable = buildPortCompatMatrixFromList ($ptlist, $pclist);
3044 if ($editable)
3045 {
3046 echo "<form method=post action='${root}process.php'>";
3047 echo "<input type=hidden name=page value='${pageno}'>";
3048 echo "<input type=hidden name=tab value='${tabno}'>";
3049 echo "<input type=hidden name=op value=save>";
3050 }
3051 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3052 echo "<tr><th class=vert_th>&nbsp;</th>";
3053 foreach ($ptlist as $name2)
3054 echo "<th>to ${name2}</th>";
3055 echo "</tr>";
3056 // Make a copy to have an independent array pointer.
3057 $ptlistY = $ptlist;
3058 $order = 'odd';
3059 foreach ($ptlistY as $type1 => $name1)
3060 {
3061 echo "<tr class=row_${order}><th class=vert_th style='border-bottom: 0px;'>from $name1</th>";
3062 foreach ($ptlist as $type2 => $name2)
3063 {
3064 echo '<td><input type=checkbox' . ($editable ? " name=atom_${type1}_${type2}" : ' disabled');
3065 echo ($pctable[$type1][$type2] ? ' checked' : '') . '></td>';
3066 }
3067 echo "</tr>\n";
3068 $order = $nextorder[$order];
3069 }
3070 echo '</table><br>';
3071 if ($editable)
3072 {
3073 echo "<input type=submit value='Save changes'>";
3074 echo "</form>";
3075 }
3076 finishPortlet();
3077 }
3078
3079 function renderConfigMainpage ()
3080 {
3081 global $pageno, $root;
3082 $children = getDirectChildPages ($pageno);
3083 echo '<ul>';
3084 // FIXME: assume all config kids to have static titles at the moment,
3085 // but use some proper abstract function later.
3086 foreach ($children as $cpageno => $child)
3087 echo "<li><a href='${root}?page=${cpageno}'>" . $child['title'] . "</li>\n";
3088 echo '';
3089 echo '</ul>';
3090 }
3091
3092 function renderRackPage ($rack_id)
3093 {
3094 if ($rack_id == 0)
3095 {
3096 showError ('Invalid rack_id', __FUNCTION__);
3097 return;
3098 }
3099 if (($rackData = getRackData ($rack_id)) == NULL)
3100 {
3101 showError ('getRackData() failed', __FUNCTION__);
3102 return;
3103 }
3104 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
3105
3106 // Left column with information.
3107 echo "<td class=pcleft>";
3108 renderRackInfoPortlet ($rackData);
3109 echo '</td>';
3110
3111 // Right column with rendered rack.
3112 echo '<td>';
3113 startPortlet ('Rack diagram');
3114 renderRack ($rack_id);
3115 finishPortlet();
3116 echo '</td>';
3117
3118 echo '</tr></table>';
3119 }
3120
3121 function renderDictionary ()
3122 {
3123 global $nextorder;
3124 $dict = getDict (TRUE);
3125 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3126 foreach ($dict as $chapter_no => $chapter)
3127 {
3128 $order = 'odd';
3129 echo "<tr><th>Chapter</th><th>refs</th><th>Word</th></tr>\n";
3130 $wc = count ($chapter['word']);
3131 echo "<tr class=row_${order}><td class=tdleft" . ($wc ? " rowspan = ${wc}" : '');
3132 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
3133 if (!$wc)
3134 echo "<td colspan=2>none</td>";
3135 else
3136 {
3137 $chap_start = TRUE;
3138 foreach ($chapter['word'] as $key => $value)
3139 {
3140 if (!$chap_start)
3141 echo "<tr class=row_${order}>";
3142 else
3143 $chap_start = FALSE;
3144 echo '<td>' . ($chapter['refcnt'][$key] ? $chapter['refcnt'][$key] : '&nbsp;') . '</td>';
3145 echo "<td><div title='key=${key}'>${value}</div></td></tr>\n";
3146 $order = $nextorder[$order];
3147 }
3148 }
3149 }
3150 echo "</table>\n<br>";
3151 }
3152
3153 function renderDictionaryEditor ()
3154 {
3155 global $root, $pageno, $tabno, $nextorder;
3156 $dict = getDict();
3157 showMessageOrError();
3158 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
3159 foreach ($dict as $chapter_no => $chapter)
3160 {
3161 $order = 'odd';
3162 echo "<tr><th>Chapter</th><th>&nbsp;</th><th>Word</th><th>&nbsp;</th></tr>\n";
3163 $wc = count ($chapter['word']);
3164 // One extra span for the new record per each chapter block.
3165 echo "<tr class=row_${order}><td class=tdleft" . ($wc ? ' rowspan = ' . ($wc + 1) : '');
3166 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
3167 echo "<form action='${root}process.php' method=post>";
3168 echo "<input type=hidden name=page value='${pageno}'>";
3169 echo "<input type=hidden name=tab value='${tabno}'>";
3170 echo "<input type=hidden name=op value=add>";
3171 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
3172 echo "<td>&nbsp;</td>";
3173 echo "<td class=tdright><input type=text name=dict_value size=32></td>";
3174 echo "<td><input type=submit value='Add new'></td>";
3175 echo '</tr></form>';
3176 $order = $nextorder[$order];
3177 foreach ($chapter['word'] as $key => $value)
3178 {
3179 echo "<form action='${root}process.php' method=post>";
3180 echo "<input type=hidden name=page value='${pageno}'>";
3181 echo "<input type=hidden name=tab value='${tabno}'>";
3182 echo "<input type=hidden name=op value='upd'>";
3183 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
3184 echo "<input type=hidden name=dict_key value='${key}'>";
3185 echo "<tr class=row_${order}><td>";
3186 // Prevent deleting words currently used somewhere.
3187 if ($chapter['refcnt'][$key])
3188 printImageHREF ('nodelete', 'referenced ' . $chapter['refcnt'][$key] . ' time(s)');
3189 else
3190 {
3191 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}&dict_key=${key}'>";
3192 printImageHREF ('delete', 'Delete word');
3193 echo "</a>";
3194 }
3195 echo '</td>';
3196 echo "<td class=tdright><input type=text name=dict_value size=32 value='${value}'></td>";
3197 echo "<td><input type=submit value=OK></td>";
3198 echo "</tr></form>\n";
3199 $order = $nextorder[$order];
3200 } // foreach ($chapter['word']
3201 } // foreach ($dict
3202 echo "</table>\n";
3203 }
3204
3205 // We don't allow to rename/delete a sticky chapter and we don't allow
3206 // to delete a non-empty chapter.
3207 function renderChaptersEditor ()
3208 {
3209 global $root, $pageno, $tabno;
3210 showMessageOrError();
3211 $dict = getDict();
3212 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
3213 echo '<tr><th>&nbsp;</th><th>Chapter name</th><th>Words</th><th>&nbsp;</th></tr>';
3214 foreach ($dict as $chapter)
3215 {
3216 $wordcount = count ($chapter['word']);
3217 $sticky = $chapter['sticky'];
3218 echo "<form action='${root}process.php' method=post>";
3219 echo "<input type=hidden name=page value='${pageno}'>";
3220 echo "<input type=hidden name=tab value='${tabno}'>";
3221 echo "<input type=hidden name=op value=upd>";
3222 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
3223 echo '<tr>';
3224 echo '<td>';
3225 if ($sticky)
3226 printImageHREF ('nodelete', 'system chapter');
3227 elseif ($wordcount > 0)
3228 printImageHREF ('nodelete', 'contains ' . $wordcount . ' word(s)');
3229 else
3230 {
3231 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}'>";
3232 printImageHREF ('delete', 'Remove chapter');
3233 echo "</a>";
3234 }
3235 echo '</td>';
3236 echo "<td><input type=text name=chapter_name value='${chapter['name']}'" . ($sticky ? ' disabled' : '') . "></td>";