7e2b349a0bc0596055bc1ccdda0a7c809b484e12
[racktables-contribs] / LinkManagement / plugins / linkmgmt.php
1 <?php
2 // TODO linkchain cytoscape create libs?
3 // linkchain all objects graph cytoscape takes ages
4 // avoid create own linkchain for every port on global map
5 // highlight port cytoscape maps
6 /*
7 * Link Management for RT >= 0.20.9
8 *
9 * Features:
10 * - create links between ports
11 * - create backend links between ports
12 * - visually display links / chains
13 * e.g.
14 * (Object)>[port] -- front --> [port]<(Object) == back == > (Object)>[port] -- front --> [port]<(Object)
15 * - Link object backend ports by name (e.g. handy for patch panels)
16 * - change/create CableID (needs jquery.jeditable.mini.js)
17 * - change/create Port Reservation Comment (needs jquery.jeditable.mini.js)
18 * - multiple backend links for supported port types (e.g. AC-in, DC)
19 * - GraphViz Maps (Objects, Ports and Links) (needs GraphViz_Image 1.3.0)
20 * - object,port or link highligthing (just click on it)
21 * - context menu to link and unlink ports
22 *
23 * Usage:
24 * 1. select "Link Management" tab
25 * 2. you should see link chains of all linked ports
26 * 3. to display all ports hit "Show All Ports" in the left upper corner
27 * 4. to link all ports with the same name of two different objects use "Link Object Ports by Name"
28 * a. select the other object you want to backend link to
29 * b. "show back ports" gives you the list of possible backend links
30 * !! Important port names have to be the same on both objects !!
31 * e.g. (Current Object):Portname -?-> Portname:(Selected Object)
32 * c. select all backend link to create (Ctrl + a for all)
33 * d. Enter backend CableID for all selected links
34 * e. "Link back" create the backend links
35 * 5. If you have an backend link within the same Object the link isn't shown until
36 * "Expand Backend Links on same Object" is hit
37 * 6. "Object Map" displays Graphviz Map of current object
38 * 7. To get a Graphviz Map of a single port click the port name on the left
39 *
40 *
41 * Changes:
42 * switch to new linkchain class
43 * - nicer looking graphviz maps
44 * - better multilink support
45 *
46 * add cytoscape.js maps
47 * - path higlighting
48 * - zooming
49 *
50 * Requirements:
51 * PHP 5 (http://php.net/)
52 * GraphViz_Image 1.3.0 or newer (http://pear.php.net/package/Image_GraphViz)
53 * GraphViz (http://www.graphviz.org/)
54 *
55 * to user cytoscape js map the following is required:
56 * create plugins/linkmgmt directory and place the following 7 files in it
57 *
58 * Cytoscape.js (http://js.cytoscape.org/)
59 * https://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/cytoscape.min.js
60 * dagre.js
61 * https://raw.githubusercontent.com/cpettitt/dagre/master/dist/dagre.min.js
62 * https://raw.githubusercontent.com/cytoscape/cytoscape.js-dagre/master/cytoscape-dagre.js
63 * qtip
64 * https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/jquery.qtip.min.css
65 *
66 * https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/jquery.qtip.min.js
67 * https://raw.githubusercontent.com/cytoscape/cytoscape.js-qtip/master/cytoscape-qtip.js
68 *
69 * jquery >= 1.10.0 (qtip requirement)
70 * https://code.jquery.com/jquery-1.11.3.min.js
71 *
72 * INSTALL:
73 *
74 * 1. create LinkBackend Table in your RackTables database
75 *
76 * Multilink table
77
78 CREATE TABLE `LinkBackend` (
79 `porta` int(10) unsigned NOT NULL DEFAULT '0',
80 `portb` int(10) unsigned NOT NULL DEFAULT '0',
81 `cable` char(64) DEFAULT NULL,
82 PRIMARY KEY (`porta`,`portb`),
83 KEY `LinkBackend_FK_a` (`porta`),
84 KEY `LinkBackend_FK_b` (`portb`),
85 CONSTRAINT `LinkBackend_FK_a` FOREIGN KEY (`porta`) REFERENCES `Port` (`id`) ON DELETE CASCADE,
86 CONSTRAINT `LinkBackend_FK_b` FOREIGN KEY (`portb`) REFERENCES `Port` (`id`) ON DELETE CASCADE
87 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 collate=utf8_unicode_ci;
88
89 * 2. copy jquery.jeditable.mini.js to plugins/linkmgmt directory (http://www.appelsiini.net/download/jquery.jeditable.mini.js)
90 * 3. copy linkmgmt.php to plugins directory
91 *
92 * Ready to go!
93 *
94 *
95 * UPDATE TABLE:
96 *
97 * Update from non-multilink table
98 * ALTER TABLE
99
100 ALTER TABLE LinkBackend ADD KEY `LinkBackend_FK_b` (`portb`);
101 ALTER TABLE LinkBackend DROP INDEX porta;
102 ALTER TABLE LinkBackend DROP INDEX portb;
103
104 * UPDATE to RT 0.20.7
105
106 ALTER TABLE LinkBackend CONVERT to CHARACTER SET utf8 COLLATE utf8_unicode_ci;
107
108 *
109 *
110 * TESTED on FreeBSD 9.0, nginx/1.0.11, php 5.3.9
111 * GraphViz_Image 1.3.0
112 *
113 * (c)2012-2015 Maik Ehinger <m.ehinger@ltur.de>
114 */
115
116 /**
117 * The newest version of this plugin can be found at:
118 *
119 * https://github.com/github138/myRT-contribs/tree/develop-0.20.x
120 *
121 */
122
123 /*************************
124 * TODO
125 *
126 * - code cleanups
127 * - bug fixing
128 *
129 * - put selected object/port top left of graph
130 * - multlink count for Graphviz maps empty or full dot
131 *
132 * - csv list
133 *
134 */
135
136 /* DEBUG */
137 //error_reporting(E_ALL);
138
139 $tab['object']['linkmgmt'] = 'Link Management';
140 $tabhandler['object']['linkmgmt'] = 'linkmgmt_tabhandler';
141 //$trigger['object']['linkmgmt'] = 'linkmgmt_tabtrigger';
142
143 $ophandler['object']['linkmgmt']['update'] = 'linkmgmt_opupdate';
144 $ophandler['object']['linkmgmt']['unlinkPort'] = 'linkmgmt_opunlinkPort';
145 $ophandler['object']['linkmgmt']['PortLinkDialog'] = 'linkmgmt_opPortLinkDialog';
146 $ophandler['object']['linkmgmt']['Help'] = 'linkmgmt_opHelp';
147
148 $ophandler['object']['linkmgmt']['map'] = 'linkmgmt_opmap';
149 $ajaxhandler['lm_mapinfo'] = 'linkmgmt_ajax_mapinfo';
150
151 $ophandler['object']['linkmgmt']['cytoscapemap'] = 'linkmgmt_cytoscapemap';
152
153 /* ------------------------------------------------- */
154
155 define('LM_MULTILINK',TRUE);
156
157 /* -------------------------------------------------- */
158
159 $lm_multilink_port_types = array(
160 16, /* AC-in */
161 //1322, /* AC-out */
162 1399, /* DC */
163 );
164
165 /* -------------------------------------------------- */
166
167 $lm_cache = array(
168 'allowcomment' => TRUE, /* RackCode {$op_set_reserve_comment} */
169 'allowlink' => TRUE, /* RackCode {$op_set_link} */
170 'allowbacklink' => TRUE, /* RackCode {$op_set_backlink} */
171 'rackinfo' => array(),
172 );
173
174 /* -------------------------------------------------- */
175
176 //function linkmgmt_tabtrigger() {
177 // return 'std';
178 //} /* linkmgmt_tabtrigger */
179
180 /* -------------------linkchain stuff------------------------------- */
181 class linkchain_cache
182 {
183 public $cache = array();
184
185 function getobject($object_id , &$rack = null)
186 {
187 if(!$object_id)
188 return null;
189
190 if(!isset($this->cache['o'.$object_id]))
191 {
192 $object = spotEntity('object', $object_id);
193 $object['IPV4OBJ'] = considerConfiguredConstraint ($object, 'IPV4OBJ_LISTSRC');
194
195 /* get more object info */
196
197 if($object['IPV4OBJ'])
198 {
199 // ip addresses
200 //amplifyCell($object); /* get ports, ipv4, ipv6, nat4 and files */
201 $object['ipv4'] = getObjectIPv4Allocations ($object_id);
202 $object['portip'] = array();
203 foreach($object['ipv4'] as $ipv4)
204 {
205 $object['portip'][$ipv4['osif']] = $ipv4['addrinfo']['ip'];
206 }
207 }
208
209 if($object['container_id'])
210 {
211 $container = $this->getobject($object['container_id']);
212 }
213
214 $this->cache['o'.$object_id] = $object;
215 }
216 else
217 $object = $this->cache['o'.$object_id];
218
219 $rack = $this->getrack($object['rack_id']);
220
221 return $object;
222 }
223
224 function getrack($rack_id)
225 {
226 // rack
227 if($rack_id)
228 {
229 if(!isset($this->cache['r'.$rack_id]))
230 {
231 $rack = spotEntity('rack', $rack_id);
232 $this->cache['r'.$rack_id] = $rack;
233 }
234 else
235 $rack = $this->cache['r'.$rack_id];
236 }
237 else
238 $rack = null;
239
240 return $rack;
241
242 }
243 }
244
245 $lc_cache = new linkchain_cache();
246
247 /* recursive class */
248 class lm_linkchain implements Iterator {
249
250 const B2B_LINK_BGCOLOR = '#d8d8d8';
251 const CURRENT_PORT_BGCOLOR = '#ffff99';
252 const CURRENT_OBJECT_BGCOLOR = '#ff0000';
253 const HL_PORT_BGCOLOR = '#A0FFA0';
254 const ALTERNATE_ROW_BGCOLOR = '#f0f0f0';
255
256 public $first = null;
257 public $last = null;
258 public $init = null;
259 public $linked = null;
260 public $linkcount = 0;
261
262 public $loop = false;
263 private $lastipobjport = null;
264
265 public $ports = array();
266
267 private $currentid = null;
268 private $back = null;
269 public $initback = null;
270
271 //public $cache = null;
272 private $object_id = null;
273
274 private $icount = 0;
275 public $exceed = false;
276
277 public $initalign = true;
278
279 public $portmulti = 0;
280 public $prevportmulti = 0;
281
282 private $initport = false;
283
284 private $lids = array(); // link ids porta portb linktype
285
286 public $pids = null; // port ids
287 public $oids = null; // object ids
288
289 /* $back = null follow front and back
290 * true follow back only
291 * false follow front only
292 * $prevport first port
293 */
294 function __construct($port_id, $back = null, $prevport = null, $reverse = false, &$pids = null, &$oids = null)
295 {
296 global $lc_cache;
297
298 $this->init = $port_id;
299
300 $this->initback = $back;
301
302 if($pids === null)
303 $this->pids = array();
304 else
305 $this->pids = &$pids;
306
307 if($oids === null)
308 $this->oids = array();
309 else
310 $this->oids = &$oids;
311
312 if($back !== null)
313 {
314 $prevport_id = $prevport['id'];
315 $prevlinktype = $this->getlinktype(!$back);
316 //if($this->setlinkid($port_id, $prevport_id, $prevlinktype))
317 {
318 $this->last = $this->_getlinks($port_id, $back, null, $reverse);
319 }
320 //else
321 {
322 // $this->loop = true;
323 // echo "SUBCHAIN LID exists $port_id $prevlinktype $prevport_id<br>";
324 }
325
326 // TODO set previous port ..use _set... function()
327 $this->ports[$port_id][$this->getlinktype(!$back)]['portcount'] = 1;
328 $this->ports[$port_id][$this->getlinktype(!$back)]['linked'] = 1;
329 $this->ports[$port_id][$this->getlinktype(!$back)]['remote_id'] = $prevport['id'];
330 $this->ports[$port_id][$this->getlinktype(!$back)]['remote_object_id'] = $prevport['object_id'];
331 $this->ports[$port_id][$this->getlinktype(!$back)]['remote_name'] = $prevport['name'];
332 $this->ports[$port_id][$this->getlinktype(!$back)]['remote_object_name'] = $prevport['object_name'];
333 $this->ports[$port_id][$this->getlinktype(!$back)]['cableid'] = $prevport['cableid'];
334
335
336 $prevport = $this->_setportlink($prevport, $this->getlinktype(!$back));
337 $prevport[$this->getlinktype($back)]['portcount'] = null;
338 $prevport[$this->getlinktype($back)]['remote_id'] = null;
339 $prevport[$this->getlinktype($back)]['remote_object_id'] = null;
340
341 $this->ports[$prevport_id] = $prevport;
342 $this->first = $prevport_id;
343 $this->linkcount++;
344
345 // self::var_dump_html($this->ports[$port_id], "PORT");
346 // self::var_dump_html($prevport, "PREVPORT");
347 $this->object_id = $_GET['object_id'];
348 }
349 else
350 {
351 // Link
352 $this->last = $this->_getlinks($port_id, false);
353
354 if(!$this->loop)
355 $this->first = $this->_getlinks($port_id, true, null, true);
356
357 $this->object_id = $this->ports[$this->init]['object_id'];
358 }
359
360 if(0)
361 if($this->loop)
362 {
363 $linktype = $this->getlinktype($back);
364 $prevlinktype = $this->getlinktype(!$back);
365
366 /* set first object */
367 $object_id = $this->ports[$port_id]['object_id'];
368 $object = $lc_cache->getobject($object_id);
369
370 if($object['IPV4OBJ'])
371 $this->lastipobjport = $port_id;
372
373 $this->first = $this->lastipobjport;
374 }
375
376 $this->linked = ($this->linkcount > 0);
377
378 if($reverse)
379 $this->reverse();
380
381 }
382
383 function setlinkid($porta, $portb, $linktype)
384 {
385 if($porta > $portb)
386 $lid = "${portb}_${porta}";
387 else
388 $lid = "${porta}_${portb}";
389
390 $lid .= $linktype;
391
392 if(isset($this->lids[$lid]))
393 return false;
394
395 $this->lids[$lid] = true;
396
397 return true;
398 }
399
400 function hasport_id($port_id)
401 {
402 if(isset($this->pids[$port_id]))
403 return true;
404 else
405 return false;
406 }
407
408 function hasobject_id($object_id)
409 {
410 if(isset($this->oids[$object_id]))
411 return true;
412 else
413 return false;
414 }
415
416 function _setportprevlink($port, $linktype, $prevport)
417 {
418 $port[$linktype] = array(
419 'cableid' => $prevport[$linktype]['cableid'],
420 'linked' => $prevport[$linktype]['linked'],
421 'portcount' => null, //$prevport[$linktype]['linked'],
422 'remote_id' => $prevport['id'],
423 'remote_name' => $prevport['name'],
424 'remote_object_id' => $prevport['object_id'],
425 'remote_object_name' => $prevport['object_name'],
426 );
427
428 return $port;
429 }
430
431 function _setportlink($port, $linktype)
432 {
433 $port[$linktype] = array(
434 'cableid' => $port['cableid'],
435 'linked' => $port['linked'],
436 'portcount' => $port['portcount'],
437 'remote_id' => $port['remote_id'],
438 'remote_name' => $port['remote_name'],
439 'remote_object_id' => $port['remote_object_id'],
440 'remote_object_name' => $port['remote_object_name'],
441 );
442
443 unset($port['cableid']);
444 unset($port['linked']);
445 unset($port['portcount']);
446 unset($port['remote_id']);
447 unset($port['remote_name']);
448 unset($port['remote_object_id']);
449 unset($port['remote_object_name']);
450
451 return $port;
452 }
453
454 function _getportlink($port)
455 {
456 $linktype = $this->getlinktype($this->back);
457 return array_merge($port, $port[$linktype], array('linktype' => $linktype));
458 }
459
460 function isback($linktable)
461 {
462 if($linktable == 'back')
463 return true;
464 else
465 return false;
466 }
467
468 function getlinktype($back)
469 {
470 return ($back ? 'back' : 'front' );
471 }
472
473 function reverse()
474 {
475 $tmp = $this->first;
476 $this->first = $this->last;
477 $this->last = $tmp;
478
479 }
480
481
482 //recursive
483 function _getlinks($port_id, $back = false, $prevport_id = null, $reverse = false)
484 {
485 global $lc_cache;
486 $linktype = $this->getlinktype($back);
487
488 if($port_id == $this->init)
489 $this->initport = true;
490
491 $ports = lm_getPortInfo($port_id, $back);
492
493 $portcount = count($ports);
494
495 $port = $ports[0];
496
497 // check for loops on multilinked ports
498 // set main port to looping one
499 if($portcount > 1)
500 foreach($ports as $mport)
501 {
502 if(isset($this->ports[$mport['remote_id']]))
503 {
504 $port = $mport;
505 break;
506 }
507 }
508
509 $remote_id = $port['remote_id'];
510
511 $port['portcount'] = $portcount;
512
513 $object_id = $port['object_id'];
514
515 $rack = null;
516 $object = $lc_cache->getobject($object_id, $rack);
517
518 $this->oids[$object_id] = true;
519
520 if($object['IPV4OBJ'])
521 $this->lastipobjport = $port_id;
522
523 if($object)
524 if(isset($object['portip'][$port['name']]))
525 $port['portip'] = $object['portip'][$port['name']];
526
527 $port = $this->_setportlink($port, $linktype);
528
529 if($prevport_id)
530 {
531 $prevlinktype = $this->getlinktype(!$back);
532 $port = $this->_setportprevlink($port, $prevlinktype, $this->ports[$prevport_id]);
533 }
534
535 //if(!$back)
536 {
537 if($prevport_id)
538 {
539 /* mutlilink: multiple previous links */
540 $prevports = lm_getPortInfo($port_id, !$back);
541
542 $prevportcount = count($prevports);
543
544 if($prevportcount > 1)
545 {
546 if($this->initport)
547 $this->initalign = false;
548
549 $port[$this->getlinktype(!$back)]['portcount'] = $prevportcount;
550
551 $lcs = array();
552 foreach($prevports as $mport)
553 {
554 if($prevport_id != $mport['remote_id'])
555 {
556 if(isset($this->pids[$mport['remote_id']]))
557 continue;
558
559 $mport['portcount'] = 1;
560 $lc = new lm_linkchain($mport['remote_id'], $back, $mport, !$reverse, $this->pids, $this->oids);
561 $lcs[$mport['remote_id']] = $lc;
562 $this->linkcount += $lc->linkcount;
563 }
564 }
565
566 $port[$this->getlinktype(!$back)]['chains'] = $lcs;
567 }
568 }
569 }
570
571 if($portcount > 1)
572 {
573 /* mutlilink: multiple links */
574
575 $lcs = array();
576 foreach($ports as $mport)
577 {
578 if($remote_id != $mport['remote_id'])
579 {
580 if(isset($this->pids[$mport['remote_id']]))
581 continue;
582
583 $mport['portcount'] = 1;
584 $lc = new lm_linkchain($mport['remote_id'], !$back, $mport, $reverse, $this->pids, $this->oids);
585 $lcs[$mport['remote_id']] = $lc;
586 $this->linkcount += $lc->linkcount;
587 }
588 }
589
590 $port[$linktype]['chains'] = $lcs;
591
592 }
593
594 if(isset($this->ports[$port_id]))
595 {
596 if(!isset($this->ports[$port_id][$linktype]))
597 {
598 $this->ports[$port_id][$linktype] = $port[$linktype];
599 }
600 }
601 else
602 $this->ports[$port_id] = $port;
603
604 $this->pids[$port_id] = true;
605
606 if($remote_id)
607 {
608 if($this->setlinkid($port_id, $remote_id, $linktype))
609 {
610 $this->linkcount++;
611 return $this->_getlinks($remote_id, !$back, $port_id, $reverse);
612 }
613 else
614 {
615 $prevlinktype = $this->getlinktype(!$back);
616 $this->loop = true;
617 if(isset($port[$prevlinktype]))
618 $this->ports[$port_id][$prevlinktype] = $port[$prevlinktype];
619
620 $this->first = $remote_id;
621 }
622 }
623
624 return $port_id;
625 }
626
627 // TODO
628 function getchaintext()
629 {
630 //$this::var_dump_html($this->ports);
631 $chain = "";
632 foreach($this as $id => $port)
633 {
634 $linktype = $port['linktype']; //$this->getlinktype();
635 if($linktype == 'front')
636 $arrow = ' --> ';
637 else
638 $arrow = ' => ';
639
640 $text = $port['object_name']." [".$port['name']."]";
641
642 if($id == $this->init)
643 $chain .= "*$text*";
644 else
645 $chain .= "$text";
646
647 $remote_id = $port['remote_id'];
648
649 if($remote_id)
650 $chain .= $arrow;
651
652 if($this->loop && $remote_id == $this->first)
653 {
654 $chain .= "LOOP!";
655 break;
656 }
657 }
658 return $chain;
659 }
660
661 function getchainlabeltrstart($rowbgcolor = '#ffffff')
662 {
663
664 $port_id = $this->init;
665
666 $initport = $this->ports[$port_id];
667
668 $urlparams = array(
669 'module' => 'redirect',
670 'page' => 'object',
671 'tab' => 'linkmgmt',
672 'op' => 'map',
673 'usemap' => 1,
674 'object_id' => $initport['object_id'],
675 );
676
677 $hl_port_id = NULL;
678 if($hl_port_id !== NULL)
679 $urlparams['hl_port_id'] = $hl_port_id;
680 else
681 $urlparams['port_id'] = $port_id;
682
683 $title = "linkcount: ".$this->linkcount."\nTypeID: ${initport['oif_id']}\nPortID: $port_id";
684
685 $onclick = 'onclick=window.open("'.makeHrefProcess(array_merge($_GET, $urlparams)).'","Map","height=500,width=800,scrollbars=yes");';
686
687 if($hl_port_id == $port_id)
688 {
689 $hlbgcolor = "bgcolor=".self::HL_PORT_BGCOLOR;
690 }
691 else
692 $hlbgcolor = "bgcolor=$rowbgcolor";
693
694 if($rowbgcolor == '#ffffff')
695 $troutlinecolor = 'grey';
696 else
697 $troutlinecolor = 'white';
698
699 /* Current Port */
700 $chainlabel = '<tr '.$hlbgcolor.' style="outline: thin solid '.$troutlinecolor.';"><td nowrap="nowrap" bgcolor='.($this->loop ? '#ff9966' : self::CURRENT_PORT_BGCOLOR).' title="'.$title.
701 '"><a '.$onclick.'>'.
702 $initport['name'].': </a></td>';
703
704 return $chainlabel;
705 }
706
707 function getchainrow($allback = false, $rowbgcolor = '#ffffff', $isprev = false)
708 {
709 $port_id = $this->init;
710
711 $initport = $this->ports[$port_id];
712 $portmulti = 0;
713 $prevportmulti = 0;
714
715 $chain = "";
716
717 $remote_id = null;
718 $portalign = false;
719 $portmultis = array();
720 $i=0;
721 foreach($this as $id => $port)
722 {
723 if($this->loop && (($isprev && $id == $this->last) || ($this->initback === null && !$isprev && $id == $this->first)))
724 $chain .= '<td bgcolor=#ff9966>LOOP</td>';
725
726 $object_text = $this->getprintobject($port);
727 $port_text = $this->getprintport($port);
728
729 if($this->initback !== null && (($isprev && $id == $this->last) || (!$isprev && $id == $this->first)))
730 {
731 $object_text = "";
732 $port_text = "";
733 }
734
735 $linktype = $port['linktype'];
736 $prevlinktype = ($linktype == 'front' ? 'back' : 'front');
737
738 if($port[$prevlinktype]['portcount'] > 1)
739 {
740 $prevportmulti++;
741 /* mutlilink: multiple previous links */
742
743 $notrowbgcolor = ($rowbgcolor == lm_linkchain::ALTERNATE_ROW_BGCOLOR ? '#ffffff' : lm_linkchain::ALTERNATE_ROW_BGCOLOR );
744 if($this->prevportmulti % 2)
745 {
746 $oddbgcolor = $rowbgcolor;
747 $evenbgcolor = $notrowbgcolor;
748 }
749 else
750 {
751 $oddbgcolor = $notrowbgcolor;
752 $evenbgcolor = $rowbgcolor;
753 }
754
755 $chain = "<td><table id=pmp frame=box><tr id=main><td><table id=pmmain align=right><tr>$chain</tr></table></td></tr><!-- main tr--><tr><td><table id=plcs align=right width=100%>"; // end table pmmain; end main tr
756
757 $mi = 0;
758 foreach($port[$prevlinktype]['chains'] as $mlc)
759 {
760 $mbgcolor = ($mi % 2 ? $evenbgcolor : $oddbgcolor);
761 $chain .= "<tr bgcolor=$mbgcolor align=right><td><table id=plc><tr>".$mlc->getchainrow($allback,$mbgcolor, true)."</tr></table><!-- end plc --></td></tr>"; // close table plc
762 $mi++;
763 }
764 $chain .= "</table><!--plcs--></td></tr></table><!--pmp--></td><td bgcolor=#ff0000></td>"; // clode tables plcs; pmp
765
766 }
767
768 if($port_text && !$this->loop && $id == $this->first)
769 {
770 $chain .= $this->_printlinkportsymbol($id, $prevlinktype);
771
772 if($prevlinktype == 'front')
773 $chain .= $this->printcomment($port);
774 }
775
776 // current port align
777 if($this->initback === null && $port_text && !$portmulti && !$prevportmulti && $this->initalign && $id == $port_id)
778 {
779 $portalign = true;
780 $port_text = "</tr></table><!--t1 current--></td><!--end 1st td--><td id=2nd width=100%><table id=t2><tr>$port_text"; // close table t1 current; clode 1st td
781 }
782
783 $object_id = $port['object_id'];
784
785 $prevobject_id = $port[$prevlinktype]['remote_object_id'];
786 $remote_object_id = $port['remote_object_id'];
787
788 if($linktype == 'front')
789 {
790 // $arrow = ' ---> ';
791 if($object_text)
792 {
793 if($prevobject_id != $object_id || $allback)
794 $chain .= $object_text."<td>></td>";
795
796 $chain .= $port_text;
797 }
798
799 }
800 else
801 {
802 // $arrow = ' ===> ';
803 if($object_text)
804 $chain .= $port_text."<td><</td>".$object_text;
805 }
806
807 if($port['portcount'] > 1)
808 {
809
810 /* mutlilink: multiple links */
811
812 $notrowbgcolor = ($rowbgcolor == lm_linkchain::ALTERNATE_ROW_BGCOLOR ? '#ffffff' : lm_linkchain::ALTERNATE_ROW_BGCOLOR );
813 if($this->portmulti % 2)
814 {
815 $oddbgcolor = $rowbgcolor;
816 $evenbgcolor = $notrowbgcolor;
817 }
818 else
819 {
820 $oddbgcolor = $notrowbgcolor;
821 $evenbgcolor = $rowbgcolor;
822 }
823
824 $chain .= "<td bgcolor=#ff0000></td><td><table id=mp frame=box>";
825
826 $multichain = "<tr><td><table id=mlcs width=100%>";
827
828 $mi = 0;
829 foreach($port['chains'] as $mlc)
830 {
831
832 $mbgcolor = ($mi % 2 ? $evenbgcolor : $oddbgcolor);
833 $multichain .= "<tr bgcolor=$mbgcolor><td><table id=t9><tr>".$mlc->getchainrow(false, $mbgcolor)."</tr></table></td></tr>";
834 $mi++;
835 }
836
837 $multichain .= "</table><!-- mlcs --></td></tr>"; // close table mlcs
838
839 $portmultis[] = $multichain;
840
841 // main
842 $chain .= "<tr id=mm><td><table id=pmm><tr>";
843
844 $portmulti++;
845
846 }
847
848 $remote_id = $port['remote_id'];
849
850 if($remote_id)
851 if($object_id != $remote_object_id || $allback || $linktype == 'front')
852 $chain .= $this->printlink($port, $linktype);
853 else
854 $chain .= "<td>></td>";
855
856 if($port_text && !($remote_id && $this->loop) && $id == $this->last)
857 {
858 $chain .= $this->_printlinkportsymbol($id, $linktype);
859
860 if($linktype == 'front')
861 $chain .= $this->printcomment($port);
862 }
863
864 $i++;
865 } // foreach port
866
867 if($this->loop && $remote_id)
868 {
869 $chain .= '<td bgcolor=#ff9966>LOOP</td>';
870 showWarning("Possible Loop on Port ($linktype) ".$initport['name']);
871 }
872
873 if($this->exceed)
874 {
875 $chain .= '<td bgcolor=#ff9966>LINKCOUNT EXCEEDED</td>';
876 $linktype = $this->getlinktype($this->back);
877 showWarning("Possible Loop linkcount(".$this->linkcount.") exceeded on Port ($linktype) ".$initport['name']);
878 }
879
880 foreach(array_reverse($portmultis) as $multitr)
881 {
882 $chain .= "</tr><!-- tr mm --></table><!-- pmm --></td></tr>$multitr</table><!-- mp--></td>"; // close table pmm; mp
883 }
884
885 if($this->initback === null)
886 {
887 // TODO width..
888 $chain = "<td id=1st".(!$portalign ? " colspan=2" : " width=1%")."><table id=t1".(!$portalign ? "" : " align=right")."><tr>$chain";
889 $chain .= "</tr></table><!-- end t1/t2 --></td><!--1st/2nd td-->"; // close table t1/t2; close 1st/2nd td
890 }
891
892 $this->portmulti += $portmulti;
893 $this->prevportmulti += $prevportmulti;
894
895 return $chain;
896 }
897
898 /*
899 */
900 function getprintobject($port) {
901 global $lc_cache;
902
903 $object_id = $port['object_id'];
904
905 if($object_id == $this->object_id) {
906 $color='color: '.self::CURRENT_OBJECT_BGCOLOR;
907 } else {
908 $color='';
909 }
910
911 $style = "font-size: 80%;";
912
913 $rack = null;
914 $object = $lc_cache->getobject($object_id, $rack);
915
916 if(!$rack)
917 $rackinfo = '<span style="'.$style.'">Unmounted</span>';
918 else
919 {
920 $rackinfo = '<a style="'.$style.'" href='.makeHref(array('page'=>'row', 'row_id'=>$rack['row_id'])).'>'.$rack['row_name']
921 .'</a>/<a style="'.$style.'" href='.makeHref(array('page'=>'rack', 'rack_id'=>$rack['id'])).'>'
922 .$rack['name'].'</a>';
923 }
924
925 return '<td><table frame=box align=center cellpadding=5 cellspacing=0><tr><td align=center><a style="font-weight:bold;'
926 .$color.'" href="'.makeHref(array('page'=>'object', 'tab' => 'linkmgmt', 'object_id' => $object_id))
927 .'"><pre>'.$object['name'].($object['container_name'] ? " (".$object['container_name'].")" : "").'</pre></a><pre>'.$rackinfo
928 .'</pre></td></tr></table></td>';
929
930 } /* printobject */
931
932 function getprintport($port, $multilink = false) {
933 global $lm_cache, $lm_multilink_port_types;
934
935 /* multilink port */
936 $multilink = in_array($port['oif_id'], $lm_multilink_port_types);
937
938 /* set bgcolor for current port */
939 if($this->initback === null && $port['id'] == $this->init) {
940 $bgcolor = 'bgcolor='.self::CURRENT_PORT_BGCOLOR;
941 $idtag = ' id='.$port['id'];
942 } else {
943 $bgcolor = 'bgcolor=#e0e0f8';
944 $idtag = '';
945 }
946
947 $mac = trim(preg_replace('/(..)/','$1:',$port['l2address']),':');
948
949 $title = "Label: ${port['label']}\nMAC: $mac\nTypeID: ${port['oif_id']}\nPortID: ${port['id']}";
950
951 if(isset($port['portip']))
952 $ip = "<br><p style=\"font-size: 80%\">".$port['portip']."</p>";
953 else
954 $ip = "";
955
956 return '<td><table><tr><td'.$idtag.' align=center '.$bgcolor.' title="'.$title.'"><pre>[<a href="'
957 .makeHref(array('page'=>'object', 'tab' => 'linkmgmt', 'object_id' => $port['object_id'], 'hl_port_id' => $port['id']))
958 .'#'.$port['id']
959 .'">'.$port['name'].'</a>]'.$ip.'</pre>'.($multilink && $lm_cache['allowbacklink'] ? $this->_getlinkportsymbol($port['id'], 'back') : '' ).'</td></tr></table></td>';
960
961 } /* printport */
962
963 /*
964 */
965 function printlink($port, $linktype) {
966
967 $link_id = $port['id']."_".$port['remote_id'];
968
969 if($linktype == 'back')
970 {
971 $arrow = '====>';
972 $link_id .= '_back';
973 }
974 else
975 $arrow = '---->';
976
977 $port_id = $port['id'];
978
979 /* link */
980 return '<td align=center>'
981 .'<pre><a class="editcable" id='.$link_id.'>'.$port['cableid']
982 ."</a></pre><pre>$arrow</pre>"
983 .$this->_printUnLinkPort($port, $linktype)
984 .'</td>';
985 } /* printlink */
986
987 /*
988 * return link symbol
989 */
990 function _getlinkportsymbol($port_id, $linktype) {
991 $retval = '<span onclick=window.open("'.makeHrefProcess(array_merge($_GET,
992 array('op' => 'PortLinkDialog','port' => $port_id,'linktype' => $linktype ))).'","name","height=800,width=800");'
993 .'>';
994
995 $img = getImageHREF ('plug', $linktype.' Link this port');
996
997 if($linktype == 'back')
998 $img = str_replace('<img',
999 '<img style="transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);-moz-transform:rotate(180deg);-webkit-transform:rotate(180deg);"',
1000 $img);
1001
1002 $retval .= $img;
1003 $retval .= "</span>";
1004 return $retval;
1005
1006 } /* _getlinkportsymbol */
1007
1008 /*
1009 * print link symbol
1010 *
1011 */
1012 function _printlinkportsymbol($port_id, $linktype = 'front') {
1013 global $lm_cache;
1014
1015 if($linktype == 'front' && !$lm_cache['allowlink'])
1016 return;
1017
1018 if($linktype != 'front' && !$lm_cache['allowbacklink'])
1019 return;
1020
1021 return "<td align=center>"
1022 .$this->_getlinkportsymbol($port_id, $linktype)
1023 ."</td>";
1024
1025 } /* _printlinkportsymbol */
1026
1027 /*
1028 */
1029 function printcomment($port) {
1030
1031 if(!empty($port['reservation_comment'])) {
1032 $prefix = '<b>Reserved: </b>';
1033 } else
1034 $prefix = '';
1035
1036 return '<td>'.$prefix.'<i><a class="editcmt" id='.$port['id'].'>'.$port['reservation_comment'].'</a></i></td>';
1037
1038 } /* printComment */
1039
1040 /*
1041 * return link cut symbol
1042 *
1043 * TODO $opspec_list
1044 */
1045 function _printUnLinkPort($src_port, $linktype) {
1046 global $lm_cache;
1047
1048 if($linktype == 'front' && !$lm_cache['allowlink'])
1049 return;
1050
1051 if($linktype != 'front' && !$lm_cache['allowbacklink'])
1052 return;
1053
1054 $dst_port = $this->ports[$src_port['remote_id']];
1055
1056 return '<a href='.
1057 makeHrefProcess(array(
1058 'op'=>'unlinkPort',
1059 'port_id'=>$src_port['id'],
1060 'remote_id' => $dst_port['id'],
1061 'object_id'=> $this->object_id, //$this->ports[$this->init]['object_id'],
1062 'tab' => 'linkmgmt',
1063 'linktype' => $linktype)).
1064 ' onclick="return confirm(\'unlink ports '.$src_port['name']. ' -> '.$dst_port['name']
1065 .' ('.$linktype.') with cable ID: '.$src_port['cableid'].'?\');">'.
1066 getImageHREF ('cut', $linktype.' Unlink this port').'</a>';
1067
1068 } /* _printUnLinkPort */
1069
1070 // TODO
1071 // html table
1072 function getchainhtml()
1073 {
1074 $remote_id = $this->first;
1075
1076 // if not Link use LinkBackend
1077 $back = $this->ports[$remote_id]['front']['remote_id'];
1078
1079 $chain = "<table>";
1080
1081 for(;$remote_id;)
1082 {
1083 $back = !$back;
1084 $linktype = $port['linktype'];
1085
1086 if($back)
1087 {
1088 // $linktable = 'LinkBackend';
1089 $arrow = ' => ';
1090 }
1091 else
1092 {
1093 // $linktable = 'Link';
1094 $arrow = ' --> ';
1095 }
1096
1097 $port = $this->ports[$remote_id][$linktype];
1098
1099 if($this->init == $remote_id)
1100 $chain .= "<tr><td><b>".$port['object_name']."</b></td><td><b> [".$port['name']."]</b></td>";
1101 else
1102 $chain .= "<tr><td>".$port['object_name']."</td><td> [".$port['name']."]</td>";
1103
1104 if($remote_id == $this->first || $remote_id == $this->last)
1105 $chain .= "<td><div name=\"port${remote_id}-status\"></div></td>";
1106 else
1107 $chain .= "<td></td>";
1108
1109 $remote_id = $port['remote_id'];
1110
1111 if($remote_id)
1112 $chain .= "<td>$arrow</td></tr>";
1113 else
1114 $chain .= "<td></td></tr>";
1115
1116 if($this->loop && $remote_id == $this->first)
1117 {
1118 $chain .= "LOOP!<br>";
1119 break;
1120 }
1121
1122 }
1123
1124 $chain .= "</table>";
1125
1126 return $chain;
1127 }
1128
1129 function getport($id)
1130 {
1131 return $this->ports[$id];
1132 }
1133
1134 /* Iterator */
1135 function rewind() {
1136 $this->currentid = $this->first;
1137
1138 $this->back = isset($this->ports[$this->currentid]['back']['remote_id']);
1139
1140 $this->icount = 0;
1141 }
1142
1143 function current() {
1144 return $this->_getportlink($this->ports[$this->currentid]);
1145 }
1146
1147 function key() {
1148 return $this->currentid;
1149 }
1150
1151 function next() {
1152 $port = $this->current();
1153 $remote_id = $port['remote_id'];
1154
1155 if($this->loop && $remote_id == $this->first)
1156 $this->currentid = false;
1157 else
1158 $this->currentid = $remote_id;
1159
1160 $this->back = !$this->back;
1161
1162 $this->icount++;
1163 }
1164
1165 function valid() {
1166
1167 /* linkcout exceeded */
1168 if($this->icount > $this->linkcount+1)
1169 {
1170 $this->exceed = true;
1171 return false;
1172 }
1173
1174 return $this->currentid;
1175 }
1176
1177 /* for debugging only */
1178 function var_dump_html(&$var, $msg = "") {
1179 echo "<pre>------------------Start Var Dump -------------$msg------------\n";
1180 var_dump($var);
1181 echo "\n---------------------END Var Dump -----------$msg-------------</pre>";
1182 }
1183 } // lm_linkchain
1184
1185 /*
1186 * from RT database.php fetchPortList()
1187 * with Link table selection
1188 * and multilink changes
1189 */
1190 function lm_fetchPortList ($sql_where_clause, $query_params = array(), $linktable = 'Link')
1191 {
1192 $query = <<<END
1193 SELECT
1194 Port.id,
1195 Port.name,
1196 Port.object_id,
1197 Object.name AS object_name,
1198 Port.l2address,
1199 Port.label,
1200 Port.reservation_comment,
1201 Port.iif_id,
1202 Port.type AS oif_id,
1203 (SELECT PortInnerInterface.iif_name FROM PortInnerInterface WHERE PortInnerInterface.id = Port.iif_id) AS iif_name,
1204 (SELECT PortOuterInterface.oif_name FROM PortOuterInterface WHERE PortOuterInterface.id = Port.type) AS oif_name,
1205
1206 lk.cable AS cableid,
1207 IF(lk.porta = Port.id, pb.id, pa.id) AS remote_id,
1208 IF(lk.porta = Port.id, pb.name, pa.name) AS remote_name,
1209 IF(lk.porta = Port.id, pb.object_id, pa.object_id) AS remote_object_id,
1210 IF(lk.porta = Port.id, ob.name, oa.name) AS remote_object_name,
1211
1212 (SELECT COUNT(*) FROM PortLog WHERE PortLog.port_id = Port.id) AS log_count,
1213 PortLog.user,
1214 UNIX_TIMESTAMP(PortLog.date) as time
1215 FROM
1216 Port
1217 INNER JOIN Object ON Port.object_id = Object.id
1218
1219 LEFT JOIN $linktable AS lk ON lk.porta = Port.id or lk.portb = Port.id
1220 LEFT JOIN Port AS pa ON pa.id = lk.porta
1221 LEFT JOIN Object AS oa ON pa.object_id = oa.id
1222 LEFT JOIN Port AS pb ON pb.id = lk.portb
1223 LEFT JOIN Object AS ob ON pb.object_id = ob.id
1224
1225 LEFT JOIN PortLog ON PortLog.id = (SELECT id FROM PortLog WHERE PortLog.port_id = Port.id ORDER BY date DESC LIMIT 1)
1226 WHERE
1227 $sql_where_clause
1228 END;
1229
1230 $result = usePreparedSelectBlade ($query, $query_params);
1231
1232 $ret = array();
1233 while ($row = $result->fetch (PDO::FETCH_ASSOC))
1234 {
1235 $row['l2address'] = l2addressFromDatabase ($row['l2address']);
1236 $row['linked'] = isset ($row['remote_id']) ? 1 : 0;
1237
1238 // last changed log
1239 $row['last_log'] = array();
1240 if ($row['log_count'])
1241 {
1242 $row['last_log']['user'] = $row['user'];
1243 $row['last_log']['time'] = $row['time'];
1244 }
1245 unset ($row['user']);
1246 unset ($row['time']);
1247
1248 $ret[] = $row;
1249 }
1250 return $ret;
1251 } /* lm_fetchPortList */
1252
1253 function lm_getPortInfo ($port_id, $back = false)
1254 {
1255 $linktable = ($back ? 'LinkBackend' : 'Link');
1256 if($back)
1257 $result = lm_fetchPortList ('Port.id = ?', array ($port_id), $linktable);
1258 else
1259 $result = fetchPortList ('Port.id = ?', array ($port_id));
1260
1261 //return empty ($result) ? NULL : $result[0];
1262 return $result;
1263 } /* lm_getPortInfo */
1264
1265 /* -------------------------------------------------------------------------- */
1266 /* -------------------------------------------------- */
1267
1268 function linkmgmt_opHelp() {
1269 ?>
1270 <table cellspacing=10><tr><th>Help</th><tr>
1271 <tr><td width=150></td><td width=150 style="font-weight:bold;color:<?php echo portlist::CURRENT_OBJECT_BGCOLOR; ?>">Current Object</td></tr>
1272 <tr><td></td><td bgcolor=<?php echo portlist::CURRENT_PORT_BGCOLOR; ?>>[current port]</td></tr>
1273 <tr><td>front link</td><td>[port]<(Object)</td><td>back link</td></tr>
1274 <tr><td>back link</td><td>(Object)>[port]</td><td>front link</td></tr>
1275 <tr><td></td><td><pre>----></pre></td><td>Front link</td></tr>
1276 <tr><td></td><td><pre>====></pre></td><td>Backend link</td></tr>
1277 <tr><td></td><td>Link Symbol</td><td>Create new link</td></tr>
1278 <tr><td></td><td>Cut Symbol</td><td>Delete link</td></tr>
1279
1280 </table>
1281
1282 <?php
1283 exit;
1284 } /* opHelp */
1285
1286 /* -------------------------------------------------- */
1287
1288 function linkmgmt_ajax_mapinfo() {
1289
1290 $object_id = NULL;
1291 $port_id = NULL;
1292 $remote_id = NULL;
1293 $linktype = NULL;
1294
1295 if(isset($_REQUEST['object_id']))
1296 $object_id = $_REQUEST['object_id'];
1297
1298 if(isset($_REQUEST['port_id']))
1299 $port_id = $_REQUEST['port_id'];
1300
1301 if(isset($_REQUEST['remote_id']))
1302 $remote_id = $_REQUEST['remote_id'];
1303
1304 if(isset($_REQUEST['linktype']))
1305 $linktype = $_REQUEST['linktype'];
1306
1307 $debug = NULL;
1308 if(isset($_REQUEST['debug']))
1309 $debug['value'] = $_REQUEST['debug'];
1310
1311 $info = array();
1312
1313 echo "<table style=\"font-size:12;\"><tr>";
1314
1315 if($port_id != NULL)
1316 {
1317 $port = new linkmgmt_RTport($port_id);
1318
1319 echo "<td>";
1320 $port->printtable('both');
1321 echo "</td>";
1322
1323 if($debug)
1324 $debug['port'] = &$port;
1325
1326 if($remote_id != NULL)
1327 {
1328
1329 $remote_port = new linkmgmt_RTport($remote_id);
1330
1331 echo "<td><table align=\"center\">";
1332
1333 // TODO cableid
1334 echo "<tr><td><pre>".($linktype == 'back' ? ' ===> ' : ' ---> ')."</pre></td></tr>";
1335
1336 $port->printunlinktr($linktype, $remote_port);
1337
1338 echo "</table></td>";
1339
1340
1341 echo "<td>";
1342 $remote_port->printtable('both');
1343 echo "</td>";
1344
1345 if($debug)
1346 $debug['remote_port'] = &$remote_port;
1347
1348 }
1349 else
1350 $port->printunlinktr();
1351
1352
1353 }
1354 echo "</tr><tr>";
1355
1356 echo "<td>";
1357 $object = linkmgmt_RTport::printobjecttable($object_id);
1358 echo "</td>";
1359
1360 if($debug)
1361 $debug['object'] = &$object;
1362
1363 if($remote_id != NULL)
1364 {
1365
1366 echo "<td></td>"; /* link */
1367 echo "<td>";
1368 $remote_object = linkmgmt_RTport::printobjecttable($remote_port->port['object_id']);
1369 echo "</td>";
1370
1371 if($debug)
1372 $debug['remote_object'] = &$remote_object;
1373 }
1374
1375 echo "</tr></table>";
1376
1377 if($debug)
1378 {
1379 echo "<pre>--- Debug ---";
1380 var_dump($debug);
1381 echo "</pre>";
1382 }
1383
1384 exit;
1385 }
1386
1387 /* -------------------------------------- */
1388 function lm_renderObjectCell ($cell)
1389 {
1390 echo "<table class='slbcell vscell'><tr><td rowspan=2 width='5%'>";
1391 printImageHREF ('OBJECT');
1392 echo '</td><td>';
1393 echo mkA ('<strong>' . niftyString ($cell['dname']) . '</strong>', 'object', $cell['id']);
1394 echo '</td></tr><tr><td>';
1395 echo count ($cell['etags']) ? ("<small>" . serializeTags ($cell['etags']) . "</small>") : '&nbsp;';
1396 echo "</td></tr></table>";
1397 }
1398 /* -------------------------------------- */
1399
1400 // TODO replace..
1401 class linkmgmt_RTport {
1402
1403 private $port_id = NULL;
1404
1405 public $port = false;
1406
1407 function __construct($port_id) {
1408
1409 $this->port = getPortInfo($port_id);
1410
1411 if($this->port === false)
1412 return;
1413
1414 /* successfully get port info */
1415 $this->port_id = $port_id;
1416
1417 } /* __construct */
1418
1419 function isvalid() {
1420 return ($port_id !== NULL);
1421 }
1422
1423 function getlinks($type = 'front') {
1424 } /* getlinks */
1425
1426 function printtable($linktype = 'front') {
1427
1428 if($this->port_id == NULL)
1429 return;
1430
1431 echo "<table>";
1432
1433 $urlparams = array(
1434 'module' => 'redirect',
1435 'page' => 'object',
1436 'tab' => 'linkmgmt',
1437 'op' => 'map',
1438 'object_id' => $this->port['object_id'],
1439 'port_id' => $this->port_id,
1440 'usemap' => 1,
1441 );
1442
1443 echo '<tr><td><a title="don\'t highlight port" href="?'.http_build_query($urlparams).'">-phl</a></td>';
1444
1445 $urlparams['hl'] = 'p';
1446 echo '<td><a title="highlight port" href="?'.http_build_query($urlparams).'">+phl</a></td></tr>';
1447
1448 $this->_printinforow($this->port,
1449 array(
1450 'id' => 'Port ID',
1451 'name' => 'Port Name',
1452 'oif_name' => 'Port Type',
1453 'l2address' => 'MAC',
1454 'reservation_comment' => 'comment',
1455 )
1456 ); /* printinforow */
1457
1458 $this->printlinktr($linktype);
1459
1460 echo "</table>";
1461 } /* printtable */
1462
1463 function printlinktr($linktype = 'front') {
1464 if($this->port_id === NULL)
1465 return;
1466
1467 $urlparams = array(
1468 'tab' => 'linkmgmt',
1469 'page' => 'object',
1470 'op'=>'PortLinkDialog',
1471 'port'=>$this->port_id,
1472 'object_id'=>$this->port['object_id'],
1473 'linktype' => $linktype,
1474 );
1475
1476 echo "<tr><td align=\"center\"><a href='".
1477 makeHrefProcess($urlparams).
1478 "'>";
1479 printImageHREF ('plug', 'Link this port');
1480 echo "</a></td></tr>";
1481 } /* link */
1482
1483 function printunlinktr($linktype = 'front', $remote_port = NULL) {
1484 if($this->port_id === NULL)
1485 return;
1486
1487 $urlparams = array(
1488 'tab' => 'linkmgmt',
1489 'op'=>'unlinkPort',
1490 'port_id'=>$this->port_id,
1491 'object_id'=>$this->port['object_id'],
1492 'linktype' => $linktype,
1493 );
1494
1495 $confirmmsg = "unlink port ".$this->port['name'];
1496
1497 if($remote_port !== NULL)
1498 {
1499 $urlparams['remote_id'] = $remote_port->port['id'];
1500 $confirmmsg .= ' -> '.$remote_port->port['name'];
1501 }
1502
1503 $confirmmsg .= " ($linktype)"; // TODO cableid
1504
1505 echo "<tr><td align=\"center\"><a href='".makeHrefProcess($urlparams).
1506 "' onclick=\"return confirm('$confirmmsg');\">";
1507 printImageHREF ('cut', 'Unlink this port');
1508 echo "</a></td></tr>";
1509
1510 } /* unlink */
1511
1512 /* TODO move to object class */
1513 static function printobjecttable($object_id = NULL) {
1514
1515 if($object_id === NULL)
1516 return;
1517
1518 $object = spotEntity ('object', $object_id);
1519
1520 if($object === false)
1521 return;
1522
1523 if($object['rack_id'])
1524 {
1525 $rack = spotEntity('rack', $object['rack_id']);
1526
1527 $object['row_name'] = $rack['row_name'];
1528 $object['rack_name'] = $rack['name'];
1529 }
1530
1531 echo "<table><tr><td>";
1532 lm_renderObjectCell($object);
1533 echo "</td></tr><tr><td><table>";
1534
1535 self::_printinforow($object,
1536 array(
1537 'id' => 'ID',
1538 'dname' => 'Name',
1539 'label' => 'Label',
1540 'rack_name' => 'Rack',
1541 'row_name' => 'Row',
1542 )
1543
1544 ); /* printinforow */
1545
1546 $urlparams = array(
1547 'module' => 'redirect',
1548 'page' => 'object',
1549 'tab' => 'linkmgmt',
1550 'op' => 'map',
1551 'object_id' => $object_id,
1552 'usemap' => 1,
1553 );
1554
1555 echo '<tr><td><a title="don\'t highlight object" href="?'.http_build_query($urlparams).'">-ohl</a></td>';
1556
1557 $urlparams['hl'] = 'o';
1558 echo '<td><a title="highlight object" href="?'.http_build_query($urlparams).'">+ohl</a></td></tr>';
1559
1560 echo "</table></td></tr></table>";
1561
1562 return $object;
1563
1564 } /* printobjecttable */
1565
1566 static function _printinforow(&$data, $config) {
1567
1568 foreach($config as $key => $name)
1569 {
1570 if(isset($data[$key]))
1571 {
1572 $value = $data[$key];
1573 if(!empty($value))
1574 echo "<tr><td align=\"right\" nowrap=\"nowrap\" style=\"font-size:10;\">$name:</td><td nowrap=\"nowrap\">$value</td></tr>";
1575 }
1576 }
1577
1578 } /* _printinforow */
1579 } /* class RTport */
1580
1581 /* -------------------------------------------------- */
1582
1583 function linkmgmt_opmap() {
1584
1585 /* display require errors "white screen of death" */
1586 $errorlevel = error_reporting();
1587 error_reporting(E_ALL);
1588
1589 require_once 'Image/GraphViz.php';
1590
1591 /*
1592 *
1593 */
1594 class lm_Image_GraphViz extends Image_GraphViz {
1595
1596 /* extend renderDotFile with additional output file
1597 */
1598 function renderDotFile($dotfile, $outputfile, $format = 'svg',
1599 $command = null, $outputfile2 = null, $format2 = null)
1600 {
1601 if (!file_exists($dotfile)) {
1602 if ($this->_returnFalseOnError) {
1603 return false;
1604 }
1605 $error = PEAR::raiseError('Could not find dot file');
1606 return $error;
1607 }
1608
1609 $oldmtime = file_exists($outputfile) ? filemtime($outputfile) : 0;
1610
1611 switch ($command) {
1612 case 'dot':
1613 case 'neato':
1614 break;
1615 default:
1616 $command = $this->graph['directed'] ? 'dot' : 'neato';
1617 }
1618 $command_orig = $command;
1619
1620 $command = $this->binPath.(($command == 'dot') ? $this->dotCommand
1621 : $this->neatoCommand);
1622
1623 $command .= ' -T'.escapeshellarg($format)
1624 .' -o'.escapeshellarg($outputfile)
1625 .($format2 !== null && $outputfile2 !== null ? ' -T'.escapeshellarg($format2).' -o'.escapeshellarg($outputfile2) : '')
1626 .' '.escapeshellarg($dotfile)
1627 .' 2>&1';
1628
1629 exec($command, $msg, $return_val);
1630
1631 clearstatcache();
1632 if (file_exists($outputfile) && filemtime($outputfile) > $oldmtime
1633 && $return_val == 0) {
1634 return true;
1635 } elseif ($this->_returnFalseOnError) {
1636 return false;
1637 }
1638 $error = PEAR::raiseError($command_orig.' command failed: '
1639 .implode("\n", $msg));
1640 return $error;
1641 }
1642 // renderDotFile
1643
1644
1645 /*
1646 */
1647 function fetch($format = 'svg', $command = null, $format2 = null, &$data2 = null)
1648 {
1649
1650 $file = $this->saveParsedGraph();
1651 if (!$file || PEAR::isError($file)) {
1652 return $file;
1653 }
1654
1655 $outputfile = $file . '.' . $format;
1656
1657 if($format2 != null && $data2 !== null)
1658 $outputfile2 = $file . '.' . $format2;
1659 else
1660 $outputfile2 = null;
1661
1662 $rendered = $this->renderDotFile($file, $outputfile, $format,
1663 $command, $outputfile2, $format2);
1664 if ($rendered !== true) {
1665 return $rendered;
1666 }
1667
1668 @unlink($file);
1669
1670 if($format2 !== null && $data2 !== null) {
1671 $fp = fopen($outputfile2, 'rb');
1672
1673 if ($fp) {
1674 $data = fread($fp, filesize($outputfile2));
1675 fclose($fp);
1676 @unlink($outputfile2);
1677
1678 $data2 = $data;
1679 } else {
1680 return $error;
1681 }
1682 }
1683
1684
1685 $fp = fopen($outputfile, 'rb');
1686
1687 if (!$fp) {
1688 if ($this->_returnFalseOnError) {
1689 return false;
1690 }
1691 $error = PEAR::raiseError('Could not read rendered file');
1692 return $error;
1693 }
1694
1695 $data = fread($fp, filesize($outputfile));
1696 fclose($fp);
1697 @unlink($outputfile);
1698
1699 return $data;
1700 }
1701 // fetch
1702
1703
1704
1705 } /* class lm_Image_GraphViz */
1706
1707 error_reporting($errorlevel);
1708
1709 $object_id = NULL;
1710 $port_id = NULL;
1711 $remote_id = NULL;
1712 $allports = false;
1713 $usemap = false;
1714 $command = NULL;
1715
1716 /* highlight object */
1717 $hl = NULL;
1718 if(isset($_REQUEST['hl']))
1719 {
1720 $hl = $_REQUEST['hl'];
1721 unset($_REQUEST['hl_object_id']);
1722 unset($_REQUEST['hl_port_id']);
1723
1724 if($hl == 'o')
1725 {
1726 unset($_GET['port_id']);
1727 unset($_GET['remote_id']);
1728 }
1729
1730 }
1731
1732 if(!$hl && isset($_REQUEST['hl_object_id']))
1733 {
1734 $hl = 'o';
1735 $object_id = $_REQUEST['hl_object_id'];
1736 $_REQUEST['object_id'] = $object_id;
1737 unset($_REQUEST['hl_object_id']);
1738 unset($_REQUEST['hl_port_id']);
1739 unset($_REQUEST['port_id']);
1740 }
1741
1742 if(isset($_REQUEST['object_id']))
1743 $object_id = $_REQUEST['object_id'];
1744
1745 if(isset($_REQUEST['type']))
1746 {
1747 $type = $_REQUEST['type'];
1748 }
1749 else
1750 $type = 'gif';
1751
1752 /* highlight port */
1753 if(!$hl && isset($_REQUEST['hl_port_id']))
1754 {
1755 $hl = 'p';
1756 $port_id = $_REQUEST['hl_port_id'];
1757 $_REQUEST['port_id'] = $port_id;
1758 unset($_REQUEST['hl_port_id']);
1759 }
1760
1761 if(isset($_REQUEST['allports']))
1762 {
1763 $allports = $_REQUEST['allports'];
1764 }
1765
1766 if(isset($_REQUEST['port_id']))
1767 {
1768 $port_id = $_REQUEST['port_id'];
1769 }
1770
1771 if(isset($_REQUEST['usemap']))
1772 $usemap = $_REQUEST['usemap'];
1773
1774 if($hl == 'p' && $port_id === NULL)
1775 {
1776 unset($_GET['hl']);
1777 unset($_GET['port_id']);
1778 unset($_GET['remote_id']);
1779 }
1780
1781 if($hl == 'o')
1782 unset($_GET['remote_id']);
1783
1784 if(isset($_REQUEST['remote_id']))
1785 $remote_id = $_REQUEST['remote_id'];
1786
1787 /* show all objects */
1788 if(isset($_REQUEST['all']))
1789 {
1790 $object_id = NULL;
1791 $port_id = NULL;
1792 $hl = NULL;
1793 unset($_GET['hl']);
1794 }
1795
1796 if(isset($_REQUEST['cmd']))
1797 $command = $_REQUEST['cmd'];
1798
1799 if(isset($_REQUEST['debug']))
1800 $debug = $_REQUEST['debug'];
1801 else
1802 $debug = False;
1803
1804 if($debug) echo "-- DEBUG --<br>";
1805
1806
1807 switch($type) {
1808 case 'gif':
1809 case 'png':
1810 case 'bmp':
1811 case 'jpeg':
1812 case 'tif':
1813 case 'wbmp':
1814 $ctype = "image/$type";
1815 break;
1816 case 'jpg':
1817 $ctype = "image/jpeg";
1818 break;
1819 case 'svg':
1820 $ctype = 'image/svg+xml';
1821 break;
1822 case 'pdf':
1823 $ctype = 'application/pdf';
1824 break;
1825 case 'cmapx':
1826 $ctype = 'text/plain';
1827 break;
1828 }
1829
1830 $start = microtime(true);
1831 $gvmap = new linkmgmt_gvmap($object_id, $port_id, $allports, $hl, $remote_id);
1832 $stop = microtime(true);
1833
1834 if($debug)
1835 echo "gvmap Time: ".( $stop - $start )."<br>";
1836
1837 if($debug) echo "-- after gvmap --<br>";
1838
1839 if($usemap)
1840 {
1841
1842 if($debug) echo "-- usemap --<br>";
1843
1844 /* add context menu to Ports, Objects, Links, ...
1845 */
1846
1847 echo "<script>
1848 function initcontextmenu() {
1849 var maps = document.getElementsByTagName('map');
1850 for(var i=0;i<maps.length;i++) {
1851 var areas = maps[i].childNodes;
1852
1853 for(j=0;j<areas.length;j++) {
1854 if(areas[j].nodeType == 1)
1855 {
1856 // console.log(areas[j].id);
1857 // attr = document.createAttribute('onmouseover','ahh');
1858 // areas[j].setAttribute(attr);
1859 // areas[j].onmouseover = 'menu(this);';
1860
1861 areas[j].addEventListener('contextmenu',menu,false);
1862 // areas[j].oncontextmenu = 'menu(this, event);';
1863 // console.log(areas[j].oncontextmenu);
1864 }
1865 }
1866
1867 }
1868
1869 };
1870
1871 function menu(event) {
1872
1873 // console.log('Menu');
1874
1875 if(!event)
1876 event = window.event;
1877
1878 var parent = event.target;
1879
1880 // console.log('--' + parent);
1881
1882 var ids = parent.id.split('-');
1883
1884 if(ids[0] == 'graph1')
1885 return false;
1886
1887 var object_id = ids[0];
1888
1889 var url ='?module=ajax&ac=lm_mapinfo&object_id=' + object_id;
1890
1891 // links ='<li><a href=' + object_id + '>Object</a></li>';
1892
1893 if(ids[1] != '')
1894 {
1895 var port_id = ids[1];
1896 url += '&port_id=' + port_id;
1897 // links += '<li><a href=' + port_id + '>Port</a></li>';
1898
1899 if(ids[2] != '')
1900 {
1901 var remote_id = ids[2];
1902
1903 if(ids[3] != '')
1904 {
1905 var linktype = ids[3];
1906 url += '&remote_id=' + remote_id + '&linktype=' + linktype;
1907 // links += '<li><a href=' + port_id + '_' + remote_id + '_' + linktype + '>Unlink</a></li>';
1908 }
1909 }
1910
1911 }
1912
1913
1914 var xmlHttp = new XMLHttpRequest();
1915 xmlHttp.open('GET', url, false);
1916 xmlHttp.send(null);
1917
1918 var infodiv = document.getElementById('info');
1919 infodiv.innerHTML = xmlHttp.responseText;
1920
1921 // linkdiv = document.getElementById('link');
1922 // linkdiv.innerHTML = links;
1923
1924 var menudiv = document.getElementById('menu');
1925 menudiv.style.position = 'absolute';
1926 menudiv.style.top = (event.clientY + document.body.scrollTop) + 'px';
1927 menudiv.style.left = (event.clientX + document.body.scrollLeft) + 'px';
1928 menudiv.style.display = '';
1929
1930 return false;
1931 };
1932
1933 function mousedown(event) {
1934 // console.log('mouse down');
1935
1936 if(!event)
1937 event = window.event;
1938
1939 if(event.button != 2)
1940 return true;
1941
1942 var menudiv = document.getElementById('menu');
1943
1944 menudiv.style.display = 'none';
1945
1946 return false;
1947 };
1948
1949 </script>";
1950
1951 echo "<body oncontextmenu=\"return false\" onmousedown=\"mousedown(event);\" onload=\"initcontextmenu();\">";
1952
1953 echo "<div id=\"menu\" style=\"display:none; background-color:#ffff90\">
1954 <div id=\"info\"></div>
1955 <ul id=\"link\" style=\"list-style-type:none\"></ul>
1956 </div>";
1957
1958 if($debug)
1959 $gvmap->setFalseOnError(False);
1960
1961 $data2 = '';
1962
1963 $start = microtime(true);
1964 $data = $gvmap->fetch($type, $command, 'cmapx', $data2);
1965 $stop = microtime(true);
1966
1967 if($debug)
1968 echo "DOT time: ".( $stop - $start )."<br>";
1969
1970 if($data === false)
1971 echo "ERROR Fetching image data!<br>";
1972
1973 if(PEAR::isError($data))
1974 echo $data->getMessage();
1975
1976 //echo $gvmap->fetch('cmapx', $command);
1977 echo $data2;
1978
1979 if($debug) echo "-- after map gvmap --<br>";
1980
1981 echo "<img src=\"data:$ctype;base64,".
1982 base64_encode($data).
1983 "\" usemap=#map$object_id />";
1984
1985 if($debug)
1986 {
1987 echo "<pre>";
1988 echo $gvmap->export();
1989 echo "</pre>";
1990
1991 echo "<pre>".$gvmap->parse()."</pre>";
1992 }
1993 }
1994 else
1995 {
1996 $gvmap->image($type);
1997 }
1998
1999 exit;
2000
2001 } /* linkmgmt_opmap */
2002
2003 class cytoscapedata
2004 {
2005 public $objects = array();
2006
2007 public $pids = array();
2008
2009 public $parents = array();
2010 public $nodes = array();
2011
2012 public $edges = NULL;
2013
2014 public $debug = null;
2015
2016 function __construct()
2017 {
2018
2019 $this->edges['parents'] = array();
2020 $this->edges['nodes'] = array();
2021 }
2022
2023 function addnode($id, $values = NULL, &$arr = NULL)
2024 {
2025 $data = array( 'id' => $id );
2026
2027 if($values != NULL)
2028 $data = $data + $values;
2029
2030 $node['data'] = $data;
2031
2032 $this->objects[] = array('group' => 'nodes') + $node;
2033
2034 switch($values['type'])
2035 {
2036 case 'port':
2037 $this->nodes[$id] = array('group' => 'nodes') + $node;
2038 break;
2039 case 'object':
2040 case 'container':
2041 $this->parents[$id] = array('group' => 'nodes') + $node;
2042 break;
2043 }
2044
2045 if($arr !== NULL)
2046 $arr[] = array('group' => 'nodes') + $node;
2047 }
2048
2049 function addedge($id, $source, $target, $values = NULL, &$arr = NULL)
2050 {
2051 $data = array(
2052 'id' => $id,
2053 'source' => $source,
2054 'target' => $target
2055 );
2056
2057 if($values != NULL)
2058 $data = $data + $values;
2059
2060 $edge['data'] = $data;
2061
2062 //$this->elements['edges'][] = $edge;
2063
2064 if($arr !== NULL)
2065 {
2066 $arr[$id] = array('group' => 'edges') + $edge;
2067 }
2068 else
2069 $this->objects[] = array('group' => 'edges') + $edge;
2070
2071 //$this->edges[] = array('group' => 'edges') + $edge;
2072 }
2073
2074 function _addobjectnode($object_id, $type = 'object')
2075 {
2076 global $lc_cache;
2077
2078 if(!isset($this->parents["o$object_id"]))
2079 {
2080 $rack = null;
2081 $object = $lc_cache->getobject($object_id, $rack);
2082
2083 $clustertitle = "${object['dname']}";
2084
2085 //has_problems
2086 //if($object['has_problems'] != 'no')
2087
2088 $rack_text = "";
2089 if(!empty($rack['row_name']) || !empty($rack['name']))
2090 {
2091 $rack_text = "${rack['row_name']} / ${rack['name']}";
2092 }
2093
2094 $data = array('label' => $object['name'], 'text' => $rack_text, 'type' => $type, 'has_problems' => $object['has_problems']);
2095
2096 $container_id = $object['container_id'];
2097 if($container_id)
2098 {
2099 $data['parent'] = "o$container_id";
2100 $this->_addobjectnode($container_id, 'container');
2101 }
2102
2103 $this->addnode('o'.$object_id, $data);
2104 }
2105
2106 }
2107
2108 // cytoscape
2109 function addlinkchain($linkchain, $index) {
2110
2111 foreach($linkchain as $id => $port)
2112 {
2113
2114 if(!$linkchain->linked)
2115 continue;
2116
2117 $this->_addobjectnode($port['object_id']);
2118
2119 $text = (isset($port['portip']) ? $port['portip'] : "" );
2120 $nodedata = array('label' => $port['name'], 'parent' => 'o'.$port['object_id'], 'text' => $text, 'type' => 'port', 'index' => $index , 'loop' => ($linkchain->loop ? '1' : '0'));
2121
2122 //$this->addnode('l_'.$port['id'], array( 'label' => $port['name'], 'parent' => 'p'.$port['id'], 'text' => $text ));
2123
2124 if($port['portcount'] > 1)
2125 foreach($port['chains'] as $mlc)
2126 {
2127 $this->addlinkchain($mlc, 0); // TODO index
2128 }
2129
2130 $prevlinktype = ($port['linktype'] == 'front' ? 'back' : 'front');
2131 if($port[$prevlinktype]['portcount'] > 1)
2132 {
2133 foreach($port[$prevlinktype]['chains'] as $mlc)
2134 {
2135 $this->addlinkchain($mlc, 0, false); // TODO index
2136 }
2137 }
2138
2139 if($port['remote_id'])
2140 {
2141
2142 $this->_addobjectnode($port['remote_object_id']);
2143
2144 $linktype = $port['linktype'];
2145 $edgedata = array('label' => $port['cableid'], 'type' => $linktype, 'loop' => ($linkchain->loop ? '1' : '0'));
2146
2147 if($linkchain->loop && $port['remote_id'] == $linkchain->first)
2148 {
2149 $nodedata['loopedge'] = array('group' => 'edges', 'data' => array( 'id' => 'le'.$port['id']."_".$port['remote_id'], 'source' => 'p'.$port['id'], 'target' => 'p'.$port['remote_id']) + $edgedata);
2150 }
2151 else
2152 {
2153
2154 $this->addedge('e'.$port['id']."_".$port['remote_id'], 'p'.$port['id'], 'p'.$port['remote_id'], $edgedata);
2155 $this->addedge('e'.$port['id']."_".$port['remote_id'], 'p'.$port['id'], 'p'.$port['remote_id'], $edgedata, $this->edges['nodes']);
2156 $id1 = $port['object_id'];
2157 if($id1 > $port['remote_object_id'])
2158 {
2159 $id1 = $port['remote_object_id'];
2160 $id2 = $port['object_id'];
2161 }
2162 else
2163 $id2 = $port['remote_object_id'];
2164
2165 $peid = "pe".$id1."_".$id2;
2166
2167 if(isset($this->edges['parents'][$peid]))
2168 $this->edges['parents'][$peid]['data']['linkcount']++;
2169 else
2170 $this->addedge($peid, 'o'.$id1, 'o'.$id2, array('type' => $linktype, 'linkcount' => 1), $this->edges['parents']);
2171 }
2172 }
2173
2174 $this->addnode('p'.$port['id'], $nodedata);
2175 }
2176
2177 if(0)
2178 if($linkchain->first != $linkchain->last )
2179 {
2180 $first = $linkchain->first;
2181 $last = $linkchain->last;
2182 $this->addedge("l${first}_${last}",'p'.$first, 'p'.$last, array('type' => 'logical', 'label' => "logical"));
2183 }
2184
2185 //portlist::var_dump_html($this->parents);
2186 }
2187
2188 function getlinkchains($object_id) {
2189
2190 $this->objects = array();
2191 $this->parents = array();
2192 $this->nodes = array();
2193 $this->edges['parents'] = array();
2194 $this->edges['nodes'] = array();
2195
2196 $this->_getlinkchains($object_id);
2197 }
2198
2199 function getelements()
2200 {
2201 //lm_linkchain::var_dump_html($this);
2202 return array('parents' => array_values($this->parents),
2203 'nodes' => array_values($this->nodes),
2204 'edges' => array(
2205 'parents' => array_values($this->edges['parents']),
2206 'nodes' => array_values($this->edges['nodes'])
2207 ),
2208 'debug' => $this->debug
2209 );
2210
2211 }
2212
2213 function gettest()
2214 {
2215 return array_merge(array_values($this->parents), array_values($this->edges['parents']));
2216 //return array_merge(array_values($this->parents), array_values($this->edges['parents']), array_values($this->nodes), array_values($this->edges['nodes']));
2217 }
2218
2219 function _getlinkchains($object_id) {
2220
2221
2222 // container
2223 // $object = spotEntity('object', $object_id);
2224 $object['ports'] = getObjectPortsAndLinks ($object_id);
2225
2226 $i = 0;
2227 foreach($object['ports'] as $key => $port)
2228 {
2229
2230 if(isset($this->pids[$port['id']]))
2231 continue;
2232
2233 $i++;
2234 $lc = new lm_linkchain($port['id']);
2235
2236 $this->pids += $lc->pids;
2237
2238 $this->addlinkchain($lc, $i);
2239
2240 }
2241
2242 $children = getEntityRelatives ('children', 'object', $object_id);
2243
2244 foreach($children as $child)
2245 $this->_getlinkchains($child['entity_id']);
2246 }
2247
2248 function allobjects()
2249 {
2250
2251 $this->objects = array();
2252 $this->parents = array();
2253 $this->nodes = array();
2254 $this->edges['parents'] = array();
2255 $this->edges['nodes'] = array();
2256
2257 $objects = listCells('object');
2258
2259 $i = 0;
2260 foreach($objects as $object)
2261 {
2262 //echo $object['id']."<br>";
2263 $this->_getlinkchains($object['id']);
2264 $i++;
2265 if($i > 20 ) break;
2266 }
2267 }
2268 }
2269
2270 function linkmgmt_cytoscapemap() {
2271
2272
2273 $object_id = $_GET['object_id'];
2274
2275 if(isset($_GET['json']))
2276 {
2277 ob_start();
2278 $data = new cytoscapedata();
2279 $data->getlinkchains($object_id);
2280 //$data->allobjects(); // ugly graph;
2281 //echo json_encode($data->objects);
2282
2283 if(ob_get_length())
2284 $data->debug = ob_get_contents();
2285
2286 ob_end_clean();
2287
2288 echo json_encode($data->getelements());
2289
2290 exit;
2291 }
2292
2293 echo (<<<HTMLEND
2294 <!DOCTYPE html>
2295 <html>
2296 <head>
2297 <style>
2298 body {
2299 font: 14px helvetica neue, helvetica, arial, sans-serif;
2300 }
2301
2302 #cy {
2303 height: 100%;
2304 width: 100%;
2305 position: absolute;
2306 left: 0;
2307 top: 0;
2308 }
2309 </style>
2310 <meta charset=utf-8 />
2311 <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
2312 <title>Compound nodes</title>
2313 <!--<script src="js/jquery-1.4.4.min.js"></script>-->
2314
2315 <script src="?module=chrome&uri=linkmgmt/jquery-1.11.3.min.js"></script>
2316 <script src="?module=chrome&uri=linkmgmt/cytoscape.min.js"></script>
2317 <script src="?module=chrome&uri=linkmgmt/dagre.min.js"></script>
2318 <script src="?module=chrome&uri=linkmgmt/cytoscape-dagre.js"></script>
2319 <link rel="stylesheet" type="text/css" href="?module=chrome&uri=linkmgmt/jquery.qtip.min.css">
2320 <script src="?module=chrome&uri=linkmgmt/jquery.qtip.min.js"></script>
2321 <script src="?module=chrome&uri=linkmgmt/cytoscape-qtip.js"></script>
2322
2323 <!--<script src="?module=chrome&uri=linkmgmt/cytoscape-css-renderer_mod.js"></script>-->
2324 <!--<script src="?module=chrome&uri=linkmgmt/cytoscape.js-navigator.js_mod"></script>-->
2325 <script>
2326 var cy = null;
2327 var cy2 = null;
2328 var layout = null;
2329 var data = null;
2330
2331 $(function(){ // on dom ready
2332 var cystyle = [
2333 {
2334 selector: 'node',
2335 css: {
2336 'content': 'data(id)',
2337 'text-wrap': 'wrap'
2338 },
2339 style: {
2340 'background-color': '#666',
2341 'label': 'data(label)',
2342 'width': 'label',
2343 'min-zoomed-font-size' : 8,
2344 'text-valign': 'center',
2345 'text-halign': 'center',
2346 'text-wrap': 'wrap',
2347 'shape': function(ele) {
2348 if(ele.data('type') != 'port')
2349 return 'rectangle';
2350 else
2351 return 'ellipse';
2352 },
2353
2354 }
2355 },
2356 {
2357 selector: '\$node > node',
2358 css: {
2359 'padding-top': '10px',
2360 'padding-left': '10px',
2361 'padding-bottom': '10px',
2362 'padding-right': '10px',
2363 'text-valign': 'top',
2364 'text-halign': 'center',
2365 'background-color': '#bbb',
2366 'min-zoomed-font-size' : 6,
2367 }
2368 },
2369 {
2370 selector: 'edge',
2371 css: {
2372 'target-arrow-shape': 'triangle',
2373 'line-color': function(ele){
2374 if(ele.data('type') == 'front')
2375 return 'black';
2376 else
2377 return 'grey';
2378 },
2379 'line-style': function(ele){
2380 if(ele.data('type') == 'front')
2381 return 'solid';
2382 else
2383 return 'dashed';
2384 },
2385 'width': function(ele){
2386 var ret = 1;
2387 if(ele.data('type') == 'front')
2388 ret = 3;
2389 else
2390 ret = 5;
2391
2392 if(1)
2393 if(ele.data('linkcount'))
2394 {
2395 ret = (ele.data('linkcount') * ret);
2396 }
2397
2398 //console.log(ele.data('id') + ret);
2399 return ret;
2400 },
2401 // 'curve-style': 'segments',
2402 'font-size': '8',
2403 'min-zoomed-font-size' : 8,
2404 'label': 'data(label)',
2405 'edge-text-rotation': 'autorotate',
2406 'source-arrow-shape': 'none',
2407 'target-arrow-shape': 'none'
2408 }
2409 },
2410 {
2411 selector: '.logical',
2412 css: {
2413 'line-color': '#0000ff',
2414 'width': 5,
2415 'curve-style': 'segments',
2416 'z-index': 0
2417 }
2418 },
2419 {
2420 selector: ':selected',
2421 css: {
2422 'background-color': 'black',
2423 'line-color': 'black',
2424 'target-arrow-color': 'black',
2425 'source-arrow-color': 'black'
2426 }
2427 },
2428 {
2429 selector: '.highlighted',
2430 css: {
2431 'line-color': '#ff0000',
2432 'background-color': '#ff0000'
2433 }
2434 },
2435 {
2436 selector: '.clhighlighted',
2437 css: {
2438 'line-color': '#00ff00',
2439 'background-color': '#00ff00'
2440 }
2441 }
2442 ];
2443
2444 var cylayout = { name: 'dagre', nodeSep: 3, ready: layoutready, stop: layoutstop };
2445
2446 function highlight(evt) {
2447
2448 //cy = evt.cy;
2449
2450 var hlclass = evt.data.hlclass;
2451 var ele = evt.cyTarget;
2452
2453 if(!ele.data)
2454 return;
2455
2456 if(ele.data('source'))
2457 ele = cy.$( '#' + ele.data('source'));
2458
2459 var id = ele.data('id');
2460
2461 if(ele.isParent())
2462 {
2463 // var childs = cy.$('#' + id).children()
2464 // childs.layout({name:'grid', cols: 2, condense: true});
2465 return;
2466 }
2467
2468
2469 // console.log('Event ' + hlclass + ' ' + id );
2470
2471 // remove existing highlights
2472 cy.$('.' + hlclass).removeClass(hlclass);
2473
2474 var hleles = ele.closedNeighborhood();
2475
2476 var hlcount = hleles.length;
2477
2478 // max 100
2479 for(i=0;i<100;i++)
2480 {
2481 hleles = hleles.closedNeighborhood();
2482
2483 if(hlcount == hleles.length)
2484 break;
2485
2486 hlcount = hleles.length;
2487
2488 }
2489 //console.log('End Loop ' + i );
2490 hleles.addClass(hlclass);
2491
2492 // console.log('Event Type: ' + evt.originalEvent.type)
2493 // console.log('Event Type: ' + evt.type)
2494
2495 if(evt.type != 'click')
2496 return;
2497
2498 var hleles2 = hleles.clone();
2499 hleles2 = hleles2.add(hleles.parents().clone());
2500
2501 //var cy2 = evt.data.cy2;
2502
2503 //var ret = evt.data.ret;
2504
2505 //var j = ret.parents.concat(ret.nodes).concat(ret.edges.nodes);
2506
2507 cy2.remove(cy2.elements());
2508 cy2.add(hleles2);
2509 //cy2.add(j);
2510 cy2.layout({name: 'dagre', rankDir: 'LR', ready: layoutready});
2511 }
2512
2513 function cytoscapeswitch(evt)
2514 {
2515 var b = evt.target;
2516
2517 var j = null;
2518 if(b.value == "1")
2519 {
2520 j = data.parents.concat(data.edges.parents);
2521 b.value = "0";
2522 b.innerHTML = "Ports";
2523 }
2524 else
2525 {
2526 j = data.parents.concat(data.nodes).concat(data.edges.nodes);
2527 b.value = "1";
2528 b.innerHTML = "Objects";
2529 }
2530
2531 //layout.stop();
2532 cy.remove(cy.elements());
2533
2534 cy.add(j);
2535
2536 cy.layout(cylayout);
2537 //layout.run();
2538 }
2539
2540 $.ajax({
2541 type: "GET",
2542 url: "{$_SERVER['PHP_SELF']}",
2543 data: { module: 'redirect',
2544 page: 'object',
2545 tab: 'linkmgmt',
2546 object_id: $object_id,
2547 op: 'cytoscapemap',
2548 json: 'json'
2549 },
2550 dataTye: 'json',
2551 error: function(){ alert("Error loading"); },
2552 success: function(jdata) {
2553
2554 data = JSON.parse(jdata);
2555
2556 if(data.debug)
2557 $('#debug').html(data.debug);
2558
2559 //j = data.parents.concat(data.edges.parents);
2560 j = data.parents.concat(data.nodes).concat(data.edges.nodes);
2561
2562 if(j.length == 0)
2563 {
2564 alert("No Links to display. Closing Window");
2565 window.close();
2566 return;
2567 }
2568
2569 cy2 = cytoscape({
2570 container: document.getElementById('cy2'),
2571 //renderer: { name: 'css' },
2572
2573 boxSelectionEnabled: false,
2574 autounselectify: true,
2575 style: cystyle,
2576 wheelSensitivity: 0.1,
2577 });
2578 cy2.style().selector('node').style('label', function(node) { return node.data('label') + '\\n' + node.data('text'); });
2579
2580 cystyle.push({
2581 selector: '.loopedge',
2582 css: {
2583 'curve-style': 'segments',
2584 }
2585 });
2586
2587 cy = cytoscape({
2588 container: document.getElementById('cy'),
2589
2590 boxSelectionEnabled: false,
2591 autounselectify: true,
2592 style: cystyle,
2593 wheelSensitivity: 0.1,
2594 elements: j,
2595 layout: cylayout,
2596 });
2597
2598 cy.on('mouseover', { hlclass: 'highlighted' }, highlight );
2599 cy.on('click', { hlclass: 'clhighlighted' }, highlight );
2600
2601 $('#switch').click(cytoscapeswitch);
2602
2603 /*
2604 TODO: node ranking
2605 */
2606
2607 if(0)
2608 cy.layout({
2609 name: 'dagre',
2610 /*
2611 nodeSep: 5,
2612 rankDir: 'TB',
2613 */
2614 //edgeSep: 10,
2615 /*
2616 edgeWeight: function(edge) {
2617 if(edge.data('type') == 'front')
2618 return 10;
2619 else
2620 return 1;
2621
2622 },
2623 */
2624 ready: layoutready,
2625 stop: layoutstop
2626 });
2627
2628 if(1)
2629 cy.$(':child').qtip({
2630
2631 content: function() {
2632
2633 return this.id() + '<br>'
2634 + 'Index: ' + this.data('index') + '<br>'
2635 + 'Name: ' + this.data('label') + '<br>'
2636 + 'Text: ' + this.data('text');
2637 },
2638 position: {
2639 my: 'top center',
2640 at: 'bottom center'
2641 },
2642 style: {
2643 classes: 'qtip-bootstrap',
2644 tip: {
2645 width: 16,
2646 height: 8
2647 },
2648 }
2649 }); // qtip
2650 } // success function
2651 });
2652
2653
2654 }); // on dom ready
2655
2656 function layoutready(evt) {
2657 var _cy = evt.cy;
2658
2659 // highlight current object
2660 var object = _cy.$('#o$object_id');
2661 if(object.data('has_problems') == 'no')
2662 object.style('background-color','#ffcccc');
2663
2664 // highlight object with problems
2665 _cy.$('node[type = "object"][has_problems != "no"]').style('background-color','#ff0000');
2666
2667 var e = _cy.$('node[loop = "1"]').style('background-color','#ff6666');
2668
2669 // console.log(e[0].data('loop'));
2670
2671 // cy.add({group: 'edges', data: {id:'l691_2991', source: 'p691', target: 'p2991', label: 'test'}, classes: 'logical'});
2672
2673 }
2674
2675 function layoutstop(evt) {
2676 var _cy = evt.cy;
2677 // cy.elements().locked = true;
2678 // cy.add({group: 'nodes', data: {id:'l2493', parent:'p2943', label: 'test'}});
2679
2680
2681 var les = _cy.$('[loopedge]');
2682
2683 if(les)
2684 {
2685 _cy.batch( function() {
2686 les.each(function(i, ele) {
2687 var le = ele.data('loopedge');
2688 var edge = _cy.add(le);
2689 edge.addClass('loopedge');
2690 //edge.style('line-color', '#ffffff'); // TypeError text-transform undefined
2691 });
2692 });
2693 _cy.$('edge[loop = "1"]').style('line-color','#ff6666');
2694 }
2695 }
2696 </script>
2697 </head>
2698 <body>
2699 <div id="cy" style="position: absolute; height: 80%; width: 100%; left: 0; top: 20%;"></div>
2700 <div id="cy2" style="position: absolute; height: 20%; width: 100%; left: 0; top: 0%;"></div>
2701 <div id="debug"></div>
2702 <button type="button" id="switch" style="position: absolute;" value="1">Object</button>
2703 </body>
2704 </html>
2705 HTMLEND
2706 ); // echo
2707 exit;
2708 }
2709
2710 /* ------------------------------------- */
2711 class linkmgmt_gvmap {
2712
2713 private $object_id = NULL;
2714 private $port_id = NULL;
2715 private $remote_id = NULL;
2716 private $hl = NULL;
2717
2718 private $gv = NULL;
2719
2720 private $ports = array();
2721
2722 private $allports = false;
2723 private $back = NULL;
2724
2725 private $alpha = 'ff';
2726
2727 private $errorlevel = NULL;
2728
2729 public $data = NULL;
2730
2731 private $pids = array();
2732
2733 function addlinkchainsobject($object_id)
2734 {
2735
2736 $object['ports'] = getObjectPortsAndLinks ($object_id);
2737
2738 if(empty($object['ports']))
2739 {
2740
2741 $hl = false;
2742 $alpha = $this->alpha;
2743 if($this->hl == 'o' && $this->object_id == $object_id)
2744 {
2745 $hl = true;
2746 $this->alpha = 'ff';
2747 }
2748
2749 $this->_addCluster($object_id, $hl, empty($object['ports']));
2750
2751 $this->alpha = $alpha;
2752 return;
2753 }
2754
2755 $i = 0;
2756 foreach($object['ports'] as $key => $port)
2757 {
2758
2759 if(isset($this->pids[$port['id']]))
2760 continue;
2761
2762 $i++;
2763 $lc = new lm_linkchain($port['id']);
2764
2765 $this->pids += $lc->pids;
2766
2767 if($this->allports ||($lc->linkcount > 0))
2768 $this->addlinkchain($lc, $i);
2769 }
2770
2771 }
2772
2773 function __construct($object_id = NULL, $port_id = NULL, $allports = false, $hl = NULL, $remote_id = NULL) {
2774 $this->allports = $allports;
2775
2776 $this->object_id = $object_id;
2777 $this->port_id = $port_id;
2778 $this->remote_id = $remote_id;
2779 $this->hl = $hl;
2780
2781 $hllabel = "";
2782
2783 /* suppress strict standards warnings for Image_GraphViz and PHP 5.4.0
2784 * output would corrupt image data
2785 */
2786 $this->errorlevel = error_reporting();
2787 error_reporting($this->errorlevel & ~E_STRICT);
2788
2789 $graphattr = array(
2790 'rankdir' => 'LR',
2791 // 'ranksep' => '0',
2792 'nodesep' => '0',
2793 // 'overlay' => false,
2794 );
2795
2796 unset($_GET['module']);
2797
2798 $_GET['all'] = 1;
2799
2800 $graphattr['URL'] = $this->_makeHrefProcess($_GET);
2801
2802 unset($_GET['all']);
2803
2804 switch($hl)
2805 {
2806 case 'o':
2807 case 'p':
2808 $this->alpha = '30';
2809 break;
2810 }
2811
2812 //$this->gv = new Image_GraphViz(true, $graphattr, "map".$object_id);
2813 $this->gv = new lm_Image_GraphViz(true, $graphattr, "map".$object_id);
2814
2815 /* --------------------------- */
2816 if($object_id === NULL)
2817 {
2818 /* all objects ! */
2819 unset($_GET['all']);
2820 $_GET['hl'] = 'o';
2821
2822 $this->gv->addAttributes(array(
2823 'label' => 'Showing all objects'.$hllabel,
2824 'labelloc' => 't',
2825 )
2826 );
2827
2828 $objects = listCells('object');
2829
2830 foreach($objects as $obj)
2831 //$this->addlinkchainsobject($obj['id']); // longer runtimes !!
2832 $this->_add($this->gv, $obj['id'], NULL); // for all still faster and nicer looking graph
2833
2834 return;
2835 }
2836 else
2837 {
2838 $object = spotEntity ('object', $object_id);
2839
2840 $this->gv->addAttributes(array(
2841 'label' => "Graph for ${object['dname']}$hllabel",
2842 'labelloc' => 't',
2843 )
2844 );
2845
2846 $this->addlinkchainsobject($object_id);
2847 //$this->_add($this->gv, $object_id, $port_id);
2848
2849 $children = getEntityRelatives ('children', 'object', $object_id); //'entity_id'
2850
2851 foreach($children as $child)
2852 $this->addlinkchainsobject($child['entity_id']);
2853 // $this->_add($this->gv, $child['entity_id'], NULL);
2854 }
2855
2856 /* add hl label */
2857 $this->gv->addAttributes(array(
2858 'label' => $this->gv->graph['attributes']['label'].$hllabel,
2859 ));
2860
2861 // portlist::var_dump_html($this->gv);
2862 // portlist::var_dump_html($this->data);
2863
2864 // echo json_encode($this->data);
2865
2866 // $this->gv->saveParsedGraph('/tmp/graph.txt');
2867 // error_reporting( E_ALL ^ E_NOTICE);
2868 } /* __construct */
2869
2870 function __destruct() {
2871 error_reporting($this->errorlevel);
2872 }
2873
2874 function _addCluster($object_id, $hl = false, $adddummy = false)
2875 {
2876 global $lc_cache;
2877
2878 $cluster_id = "c".$object_id;
2879
2880 if(
2881 !isset($this->gv->graph['clusters'][$cluster_id]) &&
2882 !isset($this->gv->graph['subgraphs'][$cluster_id])
2883 || $hl
2884 ) {
2885 $rack = null;
2886 $object = $lc_cache->getobject($object_id, $rack);
2887
2888 // $object['attr'] = getAttrValues($object_id);
2889
2890 $clusterattr = array();
2891
2892 $this->_getcolor('cluster', 'default', $this->alpha, $clusterattr, 'color');
2893 $this->_getcolor('cluster', 'default', $this->alpha, $clusterattr, 'fontcolor');
2894
2895 if($this->object_id == $object_id)
2896 {
2897 $clusterattr['rank'] = 'source';
2898
2899 $this->_getcolor('cluster', 'current', $this->alpha, $clusterattr, 'color');
2900 $this->_getcolor('cluster', 'current', $this->alpha, $clusterattr, 'fontcolor');
2901 }
2902
2903 $clustertitle = htmlspecialchars($object['dname']);
2904 $clusterattr['tooltip'] = $clustertitle;
2905
2906 unset($_GET['module']); // makeHrefProcess adds this
2907 unset($_GET['port_id']);
2908 unset($_GET['remote_id']);
2909 $_GET['object_id'] = $object_id;
2910 //$_GET['hl'] = 'o';
2911
2912 $clusterattr['URL'] = $this->_makeHrefProcess($_GET);
2913
2914 //has_problems
2915 if($object['has_problems'] != 'no')
2916 {
2917 $clusterattr['style'] = 'filled';
2918 $this->_getcolor('cluster', 'problem', $this->alpha, $clusterattr, 'fillcolor');
2919 }
2920
2921 if(!empty($object['container_name']))
2922 $clustertitle .= "<BR/>(${object['container_name']})";
2923
2924 if(!empty($rack['row_name']) || !empty($rack['name']))
2925 $clustertitle .= "<BR/><FONT point-size=\"10\">{$rack['row_name']} / {$rack['name']}</FONT>";
2926
2927 $embedin = $object['container_id'];
2928 if(empty($embedin))
2929 $embedin = 'default';
2930 else
2931 {
2932 $embedin = "c$embedin"; /* see cluster_id */
2933
2934 // TODO
2935 /* add container / cluster if not already exists */
2936 $this->addlinkchainsobject($object['container_id']);
2937 }
2938
2939 $clusterattr['id'] = "$object_id----"; /* used for js context menu */
2940
2941 $this->gv->addCluster($cluster_id, $clustertitle, $clusterattr, $embedin);
2942
2943 /* needed because of gv_image empty cluster bug (invalid foreach argument) */
2944 if($adddummy)
2945 $this->gv->addNode("dummy$cluster_id", array(
2946 // 'label' =>'No Ports found/connected',
2947 'label' =>'',
2948 'fontsize' => 0,
2949 'size' => 0,
2950 'width' => 0,
2951 'height' => 0,
2952 'shape' => 'point',
2953 'style' => 'invis',
2954 ), $cluster_id);
2955
2956
2957 }
2958 } // _addCluster
2959
2960 function _addEdge($port, $linkchain, $loopedge = false)
2961 {
2962 global $lm_multilink_port_types;
2963 if(
2964 !isset($this->gv->graph['edgesFrom'][$port['id']][$port['remote_id']]) &&
2965 !isset($this->gv->graph['edgesFrom'][$port['remote_id']][$port['id']])
2966 || $loopedge
2967 ) {
2968 $remote_id = $port['remote_id'];
2969
2970 $linktype = $port['linktype'];
2971
2972 $edgetooltip = $port['object_name'].':'.$port['name'].
2973 ' - '.$port['cableid'].' -> '.
2974 $port['remote_name'].':'.$port['remote_object_name'];
2975
2976 $edgeattr = array(
2977 'fontsize' => 8,
2978 'label' => htmlspecialchars($port['cableid']),
2979 'tooltip' => $edgetooltip,
2980 'sametail' => $linktype,
2981 'samehead' => $linktype,
2982 'arrowhead' => 'none',
2983 'arrowtail' => 'none',
2984 );
2985
2986 $this->_getcolor('edge', ($linkchain->loop ? 'loop' : 'default'), $this->alpha, $edgeattr, 'color');
2987 $this->_getcolor('edge', 'default', $this->alpha, $edgeattr, 'fontcolor');
2988
2989 if($linktype == 'back' )
2990 {
2991 $edgeattr['style'] = 'dashed';
2992
2993 /* multilink ports */
2994 if(in_array($port['oif_id'], $lm_multilink_port_types))
2995 {
2996 $edgeattr['dir'] = 'both';
2997 $edgeattr['arrowtail'] = 'dot';
2998 }
2999
3000 if(in_array($linkchain->ports[$remote_id]['oif_id'], $lm_multilink_port_types))
3001 {
3002 $edgeattr['dir'] = 'both';
3003 $edgeattr['arrowhead'] = 'dot';
3004 }
3005 }
3006
3007 if(
3008 ($port['id'] == $this->port_id && $port['remote_id'] == $this->remote_id) ||
3009 ($port['id'] == $this->remote_id && $port['remote_id'] == $this->port_id)
3010 )
3011 {
3012 $this->_getcolor('edge', 'highlight', 'ff', $edgeattr, 'color');
3013 $edgeattr['penwidth'] = 2; /* bold */
3014 }
3015
3016 unset($_GET['module']);
3017 $_GET['object_id'] = $port['object_id'];
3018 $_GET['port_id'] = $port['id'];
3019 $_GET['remote_id'] = $port['remote_id'];
3020
3021 $edgeattr['URL'] = $this->_makeHrefProcess($_GET);
3022
3023 $edgeattr['id'] = $port['object_id']."-".$port['id']."-".$port['remote_id']."-".$linktype; /* for js context menu */
3024
3025 if($loopedge)
3026 {
3027 $edgeattr = array_merge($edgeattr, array(
3028 'sametail' => 'loop',
3029 'samehead' => 'loop',
3030 'dir' => 'both',
3031 'arrowhead' => 'invodot',
3032 'arrowtail' => 'invodot',
3033 ));
3034 }
3035
3036 $this->gv->addEdge(array($port['id'] => $port['remote_id']),
3037 $edgeattr,
3038 array(
3039 $port['id'] => $linktype,
3040 $port['remote_id'] => $linktype,
3041 )
3042 );
3043
3044 }
3045 } // _addEdge
3046
3047 function addlinkchain($linkchain, $index)
3048 {
3049 global $lm_multilink_port_types;
3050
3051 $hl = false;
3052 $alpha = $this->alpha;
3053 if(
3054 ($this->hl == 'p' && $linkchain->hasport_id($this->port_id))
3055 || ($this->hl == 'o' && $linkchain->hasobject_id($this->object_id))
3056 )
3057 {
3058 $hl = true;
3059 $this->alpha = 'ff';
3060 }
3061
3062 $remote_id = null;
3063 foreach($linkchain as $id => $port)
3064 {
3065 $this->_addCluster($port['object_id'], $hl);
3066
3067 $nodelabel = htmlspecialchars("${port['name']}");
3068 $text = $nodelabel;
3069
3070 if($port['iif_id'] != '1' )
3071 {
3072 $nodelabel .= "<BR/><FONT POINT-SIZE=\"8\">${port['iif_name']}</FONT>";
3073 $text .= "\n".$port['iif_name'];
3074 }
3075
3076 $nodelabel .= "<BR/><FONT POINT-SIZE=\"8\">${port['oif_name']}</FONT>";
3077 $text .= "\n".$port['oif_name'];
3078
3079 // add ip address
3080 if(isset($port['portip']))
3081 $nodelabel .= "<BR/><FONT POINT-SIZE=\"8\">".$port['portip']."</FONT>";
3082
3083 $nodeattr = array(
3084 'label' => $nodelabel,
3085 );
3086
3087 $this->_getcolor('port', ($linkchain->loop ? 'loop' : 'default'),$this->alpha, $nodeattr, 'fontcolor');
3088 $this->_getcolor('oif_id', $port['oif_id'],$this->alpha, $nodeattr, 'color');
3089
3090 if($this->port_id == $port['id']) {
3091 $nodeattr['style'] = 'filled';
3092 $nodeattr['fillcolor'] = $this->_getcolor('port', 'current', $this->alpha);
3093 }
3094
3095 if($this->remote_id == $port['id']) {
3096 $nodeattr['style'] = 'filled';
3097 $nodeattr['fillcolor'] = $this->_getcolor('port', 'remote', $this->alpha);
3098 }
3099
3100 $nodeattr['tooltip'] = htmlspecialchars("${port['name']}");
3101
3102 unset($_GET['module']);
3103 unset($_GET['remote_id']);
3104 $_GET['object_id'] = $port['object_id'];
3105 $_GET['port_id'] = $port['id'];
3106 $_GET['hl'] = 'p';
3107
3108 $nodeattr['URL'] = $this->_makeHrefProcess($_GET);
3109 $nodeattr['id'] = "${port['object_id']}-${port['id']}--"; /* for js context menu */
3110
3111 $this->gv->addNode($port['id'],
3112 $nodeattr,
3113 "c${port['object_id']}"); /* see cluster_id */
3114
3115 $remote_id = $port['remote_id'];
3116
3117 if($port['portcount'] > 1)
3118 foreach($port['chains'] as $mlc)
3119 {
3120 $this->addlinkchain($mlc, 0); // TODO index
3121 }
3122
3123 $prevlinktype = ($port['linktype'] == 'front' ? 'back' : 'front');
3124 if($port[$prevlinktype]['portcount'] > 1)
3125 {
3126 foreach($port[$prevlinktype]['chains'] as $mlc)
3127 {
3128 $this->addlinkchain($mlc, 0, false); // TODO index
3129 }
3130 }
3131
3132 if($remote_id)
3133 $this->_addEdge($port, $linkchain);
3134
3135 } //foreach
3136
3137 if($linkchain->loop && $remote_id)
3138 {
3139 // TODO separate loop link
3140 // add loop edge
3141 $this->_addEdge($port, $linkchain, true);
3142 }
3143
3144 // reset alpha to start value
3145 $this->alpha = $alpha;
3146 }
3147
3148 function setFalseOnError($newvalue)
3149 {
3150 $this->gv->_returnFalseOnError = $newvalue;
3151 }
3152
3153 function _makeHrefProcess($array)
3154 {
3155 return str_replace('&','&amp;',makeHrefProcess($array));
3156 }
3157
3158 // !!!recursiv !!!
3159 function _add($gv, $object_id, $port_id = NULL) {
3160 global $lm_multilink_port_types;
3161
3162 if($port_id !== NULL) {
3163 if(isset($this->ports[$port_id])) {
3164 return;
3165 }
3166 }
3167
3168 if($this->back != 'front' || $port_id === NULL || $this->allports)
3169 $front = $this->_getObjectPortsAndLinks($object_id, 'front', $port_id, $this->allports);
3170 else
3171 $front = array();
3172
3173 if($this->back != 'back' || $port_id === NULL || $this->allports)
3174 $backend = $this->_getObjectPortsAndLinks($object_id, 'back', $port_id, $this->allports);
3175 else
3176 $backend = array();
3177
3178 $ports = array_merge($front,$backend);
3179
3180 /* used only for Graphviz ...
3181 * !! numeric ids cause Image_Graphviz problems on nested clusters !!
3182 */
3183 $cluster_id = "c$object_id";
3184
3185 if(empty($ports))
3186 {
3187 /* needed because of gv_image empty cluster bug (invalid foreach argument) */
3188 $gv->addNode("dummy$cluster_id", array(
3189 // 'label' =>'No Ports found/connected',
3190 'label' =>'',
3191 'fontsize' => 0,
3192 'size' => 0,
3193 'width' => 0,
3194 'height' => 0,
3195 'shape' => 'point',
3196 'style' => 'invis',
3197 ), $cluster_id);
3198
3199 /* show objects without ports */
3200 if($object_id === NULL)
3201 return;
3202 }
3203
3204 $object = NULL;
3205 if($object_id !== NULL) {
3206 if(
3207 !isset($gv->graph['clusters'][$cluster_id]) &&
3208 !isset($gv->graph['subgraphs'][$cluster_id])
3209 ) {
3210
3211 $object = spotEntity ('object', $object_id);
3212
3213 // ip addresses
3214 amplifyCell($object);
3215 $object['portip'] = array();
3216 foreach($object['ipv4'] as $ipv4)
3217 {
3218 $object['portip'][$ipv4['osif']] = $ipv4['addrinfo']['ip'];
3219 }
3220
3221 // $object['attr'] = getAttrValues($object_id);
3222
3223 $clusterattr = array();
3224
3225 $this->_getcolor('cluster', 'default', $this->alpha, $clusterattr, 'color');
3226 $this->_getcolor('cluster', 'default', $this->alpha, $clusterattr, 'fontcolor');
3227
3228 if($this->object_id == $object_id)
3229 {
3230 $clusterattr['rank'] = 'source';
3231
3232 $this->_getcolor('cluster', 'current', $this->alpha, $clusterattr, 'color');
3233 $this->_getcolor('cluster', 'current', $this->alpha, $clusterattr, 'fontcolor');
3234 }
3235
3236 $clustertitle = "${object['dname']}";
3237 $text = "${object['dname']}";
3238 $clusterattr['tooltip'] = $clustertitle;
3239
3240 unset($_GET['module']); // makeHrefProcess adds this
3241 unset($_GET['port_id']);
3242 unset($_GET['remote_id']);
3243 $_GET['object_id'] = $object_id;
3244 //$_GET['hl'] = 'o';
3245
3246 $clusterattr['URL'] = $this->_makeHrefProcess($_GET);
3247
3248 //has_problems
3249 if($object['has_problems'] != 'no')
3250 {
3251 $clusterattr['style'] = 'filled';
3252 $this->_getcolor('cluster', 'problem', $this->alpha, $clusterattr, 'fillcolor');
3253 }
3254
3255 if(!empty($object['container_name']))
3256 {
3257 $clustertitle .= "<BR/>${object['container_name']}";
3258 $text .= "\n${object['container_name']}";
3259 }
3260
3261 if($object['rack_id'])
3262 {
3263 $rack = spotEntity('rack', $object['rack_id']);
3264
3265 if(!empty($rack['row_name']) || !empty($rack['name']))
3266 {
3267 $clustertitle .= "<BR/>${rack['row_name']} / ${rack['name']}";
3268 $text .= "\n${rack['row_name']} / ${rack['name']}";
3269 }
3270 }
3271
3272 $embedin = $object['container_id'];
3273 if(empty($embedin))
3274 $embedin = 'default';
3275 else
3276 {
3277 $embedin = "c$embedin"; /* see cluster_id */
3278
3279 /* add container / cluster if not already exists */
3280 $this->_add($gv, $object['container_id'], NULL);
3281 }
3282
3283 $clusterattr['id'] = "$object_id----"; /* used for js context menu */
3284
3285 $gv->addCluster($cluster_id, $clustertitle, $clusterattr, $embedin);
3286
3287 } /* isset cluster_id */
3288 } /* object_id !== NULL */
3289
3290 foreach($ports as $key => $port) {
3291
3292 $this->back = $port['linktype'];
3293
3294 if(!isset($this->ports[$port['id']])) {
3295
3296
3297 $nodelabel = htmlspecialchars("${port['name']}");
3298 $text = $nodelabel;
3299
3300 if($port['iif_id'] != '1' )
3301 {
3302 $nodelabel .= "<BR/><FONT POINT-SIZE=\"8\">${port['iif_name']}</FONT>";
3303 $text .= "\n".$port['iif_name'];
3304 }
3305
3306 $nodelabel .= "<BR/><FONT POINT-SIZE=\"8\">${port['oif_name']}</FONT>";
3307 $text .= "\n".$port['oif_name'];
3308
3309 // add ip address
3310 if($object)
3311 if(isset($object['portip'][$port['name']]))
3312 {
3313 $nodelabel .= "<BR/><FONT POINT-SIZE=\"8\">".$object['portip'][$port['name']]."</FONT>";
3314 $text .= "\n".$object['portip'][$port['name']];
3315 }
3316
3317 $nodeattr = array(
3318 'label' => $nodelabel,
3319 );
3320
3321 $this->_getcolor('port', 'default',$this->alpha, $nodeattr, 'fontcolor');
3322 $this->_getcolor('oif_id', $port['oif_id'],$this->alpha, $nodeattr, 'color');
3323
3324 if($this->port_id == $port['id']) {
3325 $nodeattr['style'] = 'filled';
3326 $nodeattr['fillcolor'] = $this->_getcolor('port', 'current', $this->alpha);
3327 }
3328
3329 if($this->remote_id == $port['id']) {
3330 $nodeattr[