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