GUI -- [ONOS-310] - Implemented removeDevice().
- when a device is removed, we also removed any attached hosts and links. - cleaned up animations, etc. Change-Id: Ifc82f7f60dd8c7bbe4d32beeb923969713492430
Showing
7 changed files
with
224 additions
and
69 deletions
... | @@ -28,8 +28,8 @@ | ... | @@ -28,8 +28,8 @@ |
28 | "labels": [""] | 28 | "labels": [""] |
29 | }, | 29 | }, |
30 | { | 30 | { |
31 | - "class": "primary optical", | 31 | + "class": "animated optical", |
32 | - "traffic": false, | 32 | + "traffic": true, |
33 | "links": [ | 33 | "links": [ |
34 | "of:0000ffffffff0008/4-of:0000ffffffffff08/1" | 34 | "of:0000ffffffff0008/4-of:0000ffffffffff08/1" |
35 | ], | 35 | ], |
... | @@ -44,8 +44,8 @@ | ... | @@ -44,8 +44,8 @@ |
44 | "labels": [""] | 44 | "labels": [""] |
45 | }, | 45 | }, |
46 | { | 46 | { |
47 | - "class": "animated optical", | 47 | + "class": "primary optical", |
48 | - "traffic": true, | 48 | + "traffic": false, |
49 | "links": [ | 49 | "links": [ |
50 | "of:0000ffffffffff08/4-of:0000ffffffffff03/1" | 50 | "of:0000ffffffffff08/4-of:0000ffffffffff03/1" |
51 | ], | 51 | ], | ... | ... |
1 | +{ | ||
2 | + "event": "removeHost", | ||
3 | + "payload": { | ||
4 | + "id": "0E:2A:69:30:13:88/-1", | ||
5 | + "ingress": "0E:2A:69:30:13:88/-1/0-of:0000ffffffff0007/101", | ||
6 | + "egress": "of:0000ffffffff0007/101-0E:2A:69:30:13:86/-1/0", | ||
7 | + "cp": { | ||
8 | + "device": "of:0000ffffffff0007", | ||
9 | + "port": 101 | ||
10 | + }, | ||
11 | + "labels": [ | ||
12 | + "4.5.7.6", | ||
13 | + "0E:2A:69:30:13:88" | ||
14 | + ], | ||
15 | + "props": {} | ||
16 | + } | ||
17 | +} |
... | @@ -596,7 +596,7 @@ | ... | @@ -596,7 +596,7 @@ |
596 | updateHost: updateHost, | 596 | updateHost: updateHost, |
597 | 597 | ||
598 | removeInstance: removeInstance, | 598 | removeInstance: removeInstance, |
599 | - removeDevice: stillToImplement, | 599 | + removeDevice: removeDevice, |
600 | removeLink: removeLink, | 600 | removeLink: removeLink, |
601 | removeHost: removeHost, | 601 | removeHost: removeHost, |
602 | 602 | ||
... | @@ -621,9 +621,17 @@ | ... | @@ -621,9 +621,17 @@ |
621 | function addDevice(data) { | 621 | function addDevice(data) { |
622 | evTrace(data); | 622 | evTrace(data); |
623 | var device = data.payload, | 623 | var device = data.payload, |
624 | - nodeData = createDeviceNode(device); | 624 | + id = device.id, |
625 | - network.nodes.push(nodeData); | 625 | + d; |
626 | - network.lookup[nodeData.id] = nodeData; | 626 | + |
627 | + if (network.lookup[id]) { | ||
628 | + logicError('Device already added: ' + id); | ||
629 | + return; | ||
630 | + } | ||
631 | + | ||
632 | + d = createDeviceNode(device); | ||
633 | + network.nodes.push(d); | ||
634 | + network.lookup[id] = d; | ||
627 | updateNodes(); | 635 | updateNodes(); |
628 | network.force.start(); | 636 | network.force.start(); |
629 | } | 637 | } |
... | @@ -633,24 +641,24 @@ | ... | @@ -633,24 +641,24 @@ |
633 | var link = data.payload, | 641 | var link = data.payload, |
634 | result = findLink(link, 'add'), | 642 | result = findLink(link, 'add'), |
635 | bad = result.badLogic, | 643 | bad = result.badLogic, |
636 | - ldata = result.ldata; | 644 | + d = result.ldata; |
637 | 645 | ||
638 | if (bad) { | 646 | if (bad) { |
639 | logicError(bad + ': ' + link.id); | 647 | logicError(bad + ': ' + link.id); |
640 | return; | 648 | return; |
641 | } | 649 | } |
642 | 650 | ||
643 | - if (ldata) { | 651 | + if (d) { |
644 | // we already have a backing store link for src/dst nodes | 652 | // we already have a backing store link for src/dst nodes |
645 | - addLinkUpdate(ldata, link); | 653 | + addLinkUpdate(d, link); |
646 | return; | 654 | return; |
647 | } | 655 | } |
648 | 656 | ||
649 | // no backing store link yet | 657 | // no backing store link yet |
650 | - ldata = createLink(link); | 658 | + d = createLink(link); |
651 | - if (ldata) { | 659 | + if (d) { |
652 | - network.links.push(ldata); | 660 | + network.links.push(d); |
653 | - network.lookup[ldata.key] = ldata; | 661 | + network.lookup[d.key] = d; |
654 | updateLinks(); | 662 | updateLinks(); |
655 | network.force.start(); | 663 | network.force.start(); |
656 | } | 664 | } |
... | @@ -659,18 +667,26 @@ | ... | @@ -659,18 +667,26 @@ |
659 | function addHost(data) { | 667 | function addHost(data) { |
660 | evTrace(data); | 668 | evTrace(data); |
661 | var host = data.payload, | 669 | var host = data.payload, |
662 | - node = createHostNode(host), | 670 | + id = host.id, |
671 | + d, | ||
663 | lnk; | 672 | lnk; |
664 | - network.nodes.push(node); | 673 | + |
665 | - network.lookup[host.id] = node; | 674 | + if (network.lookup[id]) { |
675 | + logicError('Host already added: ' + id); | ||
676 | + return; | ||
677 | + } | ||
678 | + | ||
679 | + d = createHostNode(host); | ||
680 | + network.nodes.push(d); | ||
681 | + network.lookup[host.id] = d; | ||
666 | updateNodes(); | 682 | updateNodes(); |
667 | 683 | ||
668 | lnk = createHostLink(host); | 684 | lnk = createHostLink(host); |
669 | if (lnk) { | 685 | if (lnk) { |
670 | - node.linkData = lnk; // cache ref on its host | 686 | + d.linkData = lnk; // cache ref on its host |
671 | network.links.push(lnk); | 687 | network.links.push(lnk); |
672 | - network.lookup[host.ingress] = lnk; | 688 | + network.lookup[d.ingress] = lnk; |
673 | - network.lookup[host.egress] = lnk; | 689 | + network.lookup[d.egress] = lnk; |
674 | updateLinks(); | 690 | updateLinks(); |
675 | } | 691 | } |
676 | network.force.start(); | 692 | network.force.start(); |
... | @@ -682,9 +698,9 @@ | ... | @@ -682,9 +698,9 @@ |
682 | evTrace(data); | 698 | evTrace(data); |
683 | var inst = data.payload, | 699 | var inst = data.payload, |
684 | id = inst.id, | 700 | id = inst.id, |
685 | - instData = onosInstances[id]; | 701 | + d = onosInstances[id]; |
686 | - if (instData) { | 702 | + if (d) { |
687 | - $.extend(instData, inst); | 703 | + $.extend(d, inst); |
688 | updateInstances(); | 704 | updateInstances(); |
689 | } else { | 705 | } else { |
690 | logicError('updateInstance lookup fail. ID = "' + id + '"'); | 706 | logicError('updateInstance lookup fail. ID = "' + id + '"'); |
... | @@ -723,10 +739,10 @@ | ... | @@ -723,10 +739,10 @@ |
723 | evTrace(data); | 739 | evTrace(data); |
724 | var host = data.payload, | 740 | var host = data.payload, |
725 | id = host.id, | 741 | id = host.id, |
726 | - hostData = network.lookup[id]; | 742 | + d = network.lookup[id]; |
727 | - if (hostData) { | 743 | + if (d) { |
728 | - $.extend(hostData, host); | 744 | + $.extend(d, host); |
729 | - updateHostState(hostData); | 745 | + updateHostState(d); |
730 | } else { | 746 | } else { |
731 | logicError('updateHost lookup fail. ID = "' + id + '"'); | 747 | logicError('updateHost lookup fail. ID = "' + id + '"'); |
732 | } | 748 | } |
... | @@ -737,9 +753,9 @@ | ... | @@ -737,9 +753,9 @@ |
737 | evTrace(data); | 753 | evTrace(data); |
738 | var inst = data.payload, | 754 | var inst = data.payload, |
739 | id = inst.id, | 755 | id = inst.id, |
740 | - instData = onosInstances[id]; | 756 | + d = onosInstances[id]; |
741 | - if (instData) { | 757 | + if (d) { |
742 | - var idx = find(id, onosOrder, 'id'); | 758 | + var idx = find(id, onosOrder); |
743 | if (idx >= 0) { | 759 | if (idx >= 0) { |
744 | onosOrder.splice(idx, 1); | 760 | onosOrder.splice(idx, 1); |
745 | } | 761 | } |
... | @@ -750,13 +766,26 @@ | ... | @@ -750,13 +766,26 @@ |
750 | } | 766 | } |
751 | } | 767 | } |
752 | 768 | ||
769 | + function removeDevice(data) { | ||
770 | + evTrace(data); | ||
771 | + var device = data.payload, | ||
772 | + id = device.id, | ||
773 | + d = network.lookup[id]; | ||
774 | + if (d) { | ||
775 | + removeDeviceElement(d); | ||
776 | + } else { | ||
777 | + logicError('removeDevice lookup fail. ID = "' + id + '"'); | ||
778 | + } | ||
779 | + } | ||
780 | + | ||
753 | function removeLink(data) { | 781 | function removeLink(data) { |
754 | evTrace(data); | 782 | evTrace(data); |
755 | var link = data.payload, | 783 | var link = data.payload, |
756 | result = findLink(link, 'remove'), | 784 | result = findLink(link, 'remove'), |
757 | bad = result.badLogic; | 785 | bad = result.badLogic; |
758 | if (bad) { | 786 | if (bad) { |
759 | - logicError(bad + ': ' + link.id); | 787 | + // may have already removed link, if attached to removed device |
788 | + console.warn(bad + ': ' + link.id); | ||
760 | return; | 789 | return; |
761 | } | 790 | } |
762 | result.removeRawLink(); | 791 | result.removeRawLink(); |
... | @@ -766,14 +795,16 @@ | ... | @@ -766,14 +795,16 @@ |
766 | evTrace(data); | 795 | evTrace(data); |
767 | var host = data.payload, | 796 | var host = data.payload, |
768 | id = host.id, | 797 | id = host.id, |
769 | - hostData = network.lookup[id]; | 798 | + d = network.lookup[id]; |
770 | - if (hostData) { | 799 | + if (d) { |
771 | - removeHostElement(hostData); | 800 | + removeHostElement(d, true); |
772 | } else { | 801 | } else { |
773 | - logicError('removeHost lookup fail. ID = "' + id + '"'); | 802 | + // may have already removed host, if attached to removed device |
803 | + console.warn('removeHost lookup fail. ID = "' + id + '"'); | ||
774 | } | 804 | } |
775 | } | 805 | } |
776 | 806 | ||
807 | + // the following events are server responses to user actions | ||
777 | function showSummary(data) { | 808 | function showSummary(data) { |
778 | evTrace(data); | 809 | evTrace(data); |
779 | populateSummary(data.payload); | 810 | populateSummary(data.payload); |
... | @@ -828,14 +859,6 @@ | ... | @@ -828,14 +859,6 @@ |
828 | 859 | ||
829 | // ............................... | 860 | // ............................... |
830 | 861 | ||
831 | - function stillToImplement(data) { | ||
832 | - var p = data.payload; | ||
833 | - note(data.event, p.id); | ||
834 | - if (!config.useLiveData) { | ||
835 | - network.view.alert('Not yet implemented: "' + data.event + '"'); | ||
836 | - } | ||
837 | - } | ||
838 | - | ||
839 | function unknownEvent(data) { | 862 | function unknownEvent(data) { |
840 | console.warn('Unknown event type: "' + data.event + '"', data); | 863 | console.warn('Unknown event type: "' + data.event + '"', data); |
841 | } | 864 | } |
... | @@ -854,17 +877,6 @@ | ... | @@ -854,17 +877,6 @@ |
854 | function getSel(idx) { | 877 | function getSel(idx) { |
855 | return selections[selectOrder[idx]]; | 878 | return selections[selectOrder[idx]]; |
856 | } | 879 | } |
857 | - function getSelId(idx) { | ||
858 | - return getSel(idx).obj.id; | ||
859 | - } | ||
860 | - function getSelIds(start, endOffset) { | ||
861 | - var end = selectOrder.length - endOffset; | ||
862 | - var ids = []; | ||
863 | - selectOrder.slice(start, end).forEach(function (d) { | ||
864 | - ids.push(getSelId(d)); | ||
865 | - }); | ||
866 | - return ids; | ||
867 | - } | ||
868 | function allSelectionsClass(cls) { | 880 | function allSelectionsClass(cls) { |
869 | for (var i=0, n=nSel(); i<n; i++) { | 881 | for (var i=0, n=nSel(); i<n; i++) { |
870 | if (getSel(i).obj.class !== cls) { | 882 | if (getSel(i).obj.class !== cls) { |
... | @@ -895,7 +907,6 @@ | ... | @@ -895,7 +907,6 @@ |
895 | updateDeviceColors(); | 907 | updateDeviceColors(); |
896 | } | 908 | } |
897 | 909 | ||
898 | - | ||
899 | function toggleSummary() { | 910 | function toggleSummary() { |
900 | if (!summaryPane.isVisible()) { | 911 | if (!summaryPane.isVisible()) { |
901 | requestSummary(); | 912 | requestSummary(); |
... | @@ -1841,14 +1852,18 @@ | ... | @@ -1841,14 +1852,18 @@ |
1841 | 1852 | ||
1842 | // host node exits.... | 1853 | // host node exits.... |
1843 | exiting.filter('.host').each(function (d) { | 1854 | exiting.filter('.host').each(function (d) { |
1844 | - var node = d3.select(this); | 1855 | + var node = d.el; |
1856 | + node.select('use') | ||
1857 | + .style('opacity', 0.5) | ||
1858 | + .transition() | ||
1859 | + .duration(800) | ||
1860 | + .style('opacity', 0); | ||
1845 | 1861 | ||
1846 | node.select('text') | 1862 | node.select('text') |
1847 | .style('opacity', 0.5) | 1863 | .style('opacity', 0.5) |
1848 | .transition() | 1864 | .transition() |
1849 | - .duration(1000) | 1865 | + .duration(800) |
1850 | .style('opacity', 0); | 1866 | .style('opacity', 0); |
1851 | - // note, leave <g>.remove to remove this element | ||
1852 | 1867 | ||
1853 | node.select('circle') | 1868 | node.select('circle') |
1854 | .style('stroke-fill', '#555') | 1869 | .style('stroke-fill', '#555') |
... | @@ -1857,11 +1872,22 @@ | ... | @@ -1857,11 +1872,22 @@ |
1857 | .transition() | 1872 | .transition() |
1858 | .duration(1500) | 1873 | .duration(1500) |
1859 | .attr('r', 0); | 1874 | .attr('r', 0); |
1860 | - // note, leave <g>.remove to remove this element | ||
1861 | - | ||
1862 | }); | 1875 | }); |
1863 | 1876 | ||
1864 | - // TODO: device node exit animation | 1877 | + // device node exits.... |
1878 | + exiting.filter('.device').each(function (d) { | ||
1879 | + var node = d.el; | ||
1880 | + node.select('use') | ||
1881 | + .style('opacity', 0.5) | ||
1882 | + .transition() | ||
1883 | + .duration(800) | ||
1884 | + .style('opacity', 0); | ||
1885 | + | ||
1886 | + node.selectAll('rect') | ||
1887 | + .style('stroke-fill', '#555') | ||
1888 | + .style('fill', '#888') | ||
1889 | + .style('opacity', 0.5); | ||
1890 | + }); | ||
1865 | 1891 | ||
1866 | network.force.resume(); | 1892 | network.force.resume(); |
1867 | } | 1893 | } |
... | @@ -1968,7 +1994,7 @@ | ... | @@ -1968,7 +1994,7 @@ |
1968 | } | 1994 | } |
1969 | 1995 | ||
1970 | function find(key, array, tag) { | 1996 | function find(key, array, tag) { |
1971 | - var _tag = tag || 'key', | 1997 | + var _tag = tag || 'id', |
1972 | idx, n, d; | 1998 | idx, n, d; |
1973 | for (idx = 0, n = array.length; idx < n; idx++) { | 1999 | for (idx = 0, n = array.length; idx < n; idx++) { |
1974 | d = array[idx]; | 2000 | d = array[idx]; |
... | @@ -1979,8 +2005,8 @@ | ... | @@ -1979,8 +2005,8 @@ |
1979 | return -1; | 2005 | return -1; |
1980 | } | 2006 | } |
1981 | 2007 | ||
1982 | - function removeLinkElement(linkData) { | 2008 | + function removeLinkElement(d) { |
1983 | - var idx = find(linkData.key, network.links), | 2009 | + var idx = find(d.key, network.links, 'key'), |
1984 | removed; | 2010 | removed; |
1985 | if (idx >=0) { | 2011 | if (idx >=0) { |
1986 | // remove from links array | 2012 | // remove from links array |
... | @@ -1992,20 +2018,64 @@ | ... | @@ -1992,20 +2018,64 @@ |
1992 | } | 2018 | } |
1993 | } | 2019 | } |
1994 | 2020 | ||
1995 | - function removeHostElement(hostData) { | 2021 | + function removeHostElement(d, upd) { |
2022 | + var lu = network.lookup; | ||
1996 | // first, remove associated hostLink... | 2023 | // first, remove associated hostLink... |
1997 | - removeLinkElement(hostData.linkData); | 2024 | + removeLinkElement(d.linkData); |
2025 | + | ||
2026 | + // remove hostLink bindings | ||
2027 | + delete lu[d.ingress]; | ||
2028 | + delete lu[d.egress]; | ||
1998 | 2029 | ||
1999 | // remove from lookup cache | 2030 | // remove from lookup cache |
2000 | - delete network.lookup[hostData.id]; | 2031 | + delete lu[d.id]; |
2001 | // remove from nodes array | 2032 | // remove from nodes array |
2002 | - var idx = find(hostData.id, network.nodes); | 2033 | + var idx = find(d.id, network.nodes); |
2034 | + network.nodes.splice(idx, 1); | ||
2035 | + // remove from SVG | ||
2036 | + // NOTE: upd is false if we were called from removeDeviceElement() | ||
2037 | + if (upd) { | ||
2038 | + updateNodes(); | ||
2039 | + network.force.resume(); | ||
2040 | + } | ||
2041 | + } | ||
2042 | + | ||
2043 | + | ||
2044 | + function removeDeviceElement(d) { | ||
2045 | + var id = d.id; | ||
2046 | + // first, remove associated hosts and links.. | ||
2047 | + findAttachedHosts(id).forEach(removeHostElement); | ||
2048 | + findAttachedLinks(id).forEach(removeLinkElement); | ||
2049 | + | ||
2050 | + // remove from lookup cache | ||
2051 | + delete network.lookup[id]; | ||
2052 | + // remove from nodes array | ||
2053 | + var idx = find(id, network.nodes); | ||
2003 | network.nodes.splice(idx, 1); | 2054 | network.nodes.splice(idx, 1); |
2004 | // remove from SVG | 2055 | // remove from SVG |
2005 | updateNodes(); | 2056 | updateNodes(); |
2006 | network.force.resume(); | 2057 | network.force.resume(); |
2007 | } | 2058 | } |
2008 | 2059 | ||
2060 | + function findAttachedHosts(devId) { | ||
2061 | + var hosts = []; | ||
2062 | + network.nodes.forEach(function (d) { | ||
2063 | + if (d.class === 'host' && d.cp.device === devId) { | ||
2064 | + hosts.push(d); | ||
2065 | + } | ||
2066 | + }); | ||
2067 | + return hosts; | ||
2068 | + } | ||
2069 | + | ||
2070 | + function findAttachedLinks(devId) { | ||
2071 | + var links = []; | ||
2072 | + network.links.forEach(function (d) { | ||
2073 | + if (d.source.id === devId || d.target.id === devId) { | ||
2074 | + links.push(d); | ||
2075 | + } | ||
2076 | + }); | ||
2077 | + return links; | ||
2078 | + } | ||
2009 | 2079 | ||
2010 | function tick() { | 2080 | function tick() { |
2011 | node.attr({ | 2081 | node.attr({ | ... | ... |
-
Please register or login to post a comment