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