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