Remove links from topology when port goes down
[controller.git] / opendaylight / md-sal / topology-manager / src / main / java / org / opendaylight / md / controller / topology / manager / FlowCapableTopologyExporter.xtend
1 package org.opendaylight.md.controller.topology.manager
2
3 import com.google.common.collect.FluentIterable
4 import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader
5 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction
6 import org.opendaylight.controller.sal.binding.api.data.DataProviderService
7 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated
8 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated
9 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.FlowTopologyDiscoveryListener
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkDiscovered
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkOverutilized
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkRemoved
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkUtilizationNormal
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryListener
21 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology
22 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NodeId
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TopologyId
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.TpId
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.Topology
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyBuilder
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.TopologyKey
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Link
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.Node
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.NodeKey
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPoint
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.network.topology.topology.node.TerminationPointKey
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
34
35 import static extension org.opendaylight.md.controller.topology.manager.FlowCapableNodeMapping.*
36
37 class FlowCapableTopologyExporter implements //
38 FlowTopologyDiscoveryListener, //
39 OpendaylightInventoryListener //
40 {
41
42     var TopologyKey topology = new TopologyKey(new TopologyId("flow:1"));
43
44     @Property
45     var DataProviderService dataService;
46     
47     def start() {
48         val tb = new TopologyBuilder();
49         tb.setKey(topology);
50         val path = InstanceIdentifier.builder(NetworkTopology).child(Topology,topology).toInstance;
51         val top = tb.build();
52         val it = dataService.beginTransaction
53         putOperationalData(path,top);
54         commit()       
55     }
56
57     override onNodeRemoved(NodeRemoved notification) {
58         val nodeId = notification.nodeRef.nodeKey.id.toToplogyNodeId()
59         val nodeInstance = notification.nodeRef.toNodeIdentifier()
60
61         val it = dataService.beginTransaction
62         removeOperationalData(nodeInstance);
63         removeAffectedLinks(it,nodeId)
64         commit()
65
66     }
67
68     override onNodeUpdated(NodeUpdated notification) {
69         val fcnu = notification.getAugmentation(FlowCapableNodeUpdated)
70         if(fcnu != null) {
71             val node = notification.id.toToplogyNodeId.toTopologyNode(notification.nodeRef)
72             val path = notification.id.toToplogyNodeId.nodePath;
73             val it = dataService.beginTransaction
74             putOperationalData(path, node);
75             commit()
76         }
77     }
78
79     override onNodeConnectorRemoved(NodeConnectorRemoved notification) {
80         val tpInstance = notification.nodeConnectorRef.toTerminationPointIdentifier;
81         val tpId = notification.nodeConnectorRef.nodeConnectorKey.id.toTerminationPointId;
82         val it = dataService.beginTransaction
83         removeOperationalData(tpInstance);
84         removeAffectedLinks(it,tpId)
85         commit()
86
87     }
88
89     override onNodeConnectorUpdated(NodeConnectorUpdated notification) {
90         val fcncu = notification.getAugmentation(FlowCapableNodeConnectorUpdated)
91         if(fcncu != null) {
92             val nodeId = notification.nodeConnectorRef.nodeKey.id.toToplogyNodeId;
93             val TerminationPoint point = notification.id.toTerminationPointId.toTerminationPoint(notification.nodeConnectorRef);
94             val path = tpPath(nodeId, point.key.tpId);
95     
96             val it = dataService.beginTransaction
97             putOperationalData(path, point);
98             if((fcncu.state != null && fcncu.state.linkDown) || (fcncu.configuration != null && fcncu.configuration.PORTDOWN)) {
99                 removeAffectedLinks(it,point.tpId)
100             }
101             commit()     
102        }
103     }
104
105     override onLinkDiscovered(LinkDiscovered notification) {
106         val link = notification.toTopologyLink;
107         val path = link.linkPath;
108         val it = dataService.beginTransaction
109         putOperationalData(path, link);
110         commit()
111     }
112
113     override onLinkOverutilized(LinkOverutilized notification) {
114         // NOOP
115     }
116
117     override onLinkRemoved(LinkRemoved notification) {
118         val path = notification.toTopologyLink.linkPath
119         val it = dataService.beginTransaction
120         removeOperationalData(path);
121         commit()
122     }
123
124     override onLinkUtilizationNormal(LinkUtilizationNormal notification) {
125         // NOOP
126     }
127
128     def InstanceIdentifier<Node> toNodeIdentifier(NodeRef ref) {
129         val invNodeKey = ref.nodeKey
130
131         val nodeKey = new NodeKey(invNodeKey.id.toToplogyNodeId);
132         return InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
133             toInstance;
134     }
135
136     def InstanceIdentifier<TerminationPoint> toTerminationPointIdentifier(NodeConnectorRef ref) {
137         val invNodeKey = ref.nodeKey
138         val invNodeConnectorKey = ref.nodeConnectorKey
139         return tpPath(invNodeKey.id.toToplogyNodeId(), invNodeConnectorKey.id.toTerminationPointId())
140     }
141
142     private def void removeAffectedLinks(DataModificationTransaction transaction, NodeId id) {
143         val reader = TypeSafeDataReader.forReader(transaction)
144         val topologyPath = InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).toInstance;
145         val topologyData = reader.readOperationalData(topologyPath);
146         if (topologyData === null) {
147             return;
148         }
149         val affectedLinkInstances = FluentIterable.from(topologyData.link).filter[
150             source.sourceNode == id || destination.destNode == id].transform [
151             //
152             InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Link, key).toInstance
153         //
154         ]
155         for(affectedLink : affectedLinkInstances) {
156             transaction.removeOperationalData(affectedLink);
157         }
158     }
159     
160     private def void removeAffectedLinks(DataModificationTransaction transaction, TpId id) {
161         val reader = TypeSafeDataReader.forReader(transaction)
162         val topologyPath = InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).toInstance;
163         val topologyData = reader.readOperationalData(topologyPath);
164         if (topologyData === null) {
165             return;
166         }
167         val affectedLinkInstances = FluentIterable.from(topologyData.link).filter[
168             source.sourceTp == id || destination.destTp == id].transform [
169             //
170             InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Link, key).toInstance
171         //
172         ]
173         for(affectedLink : affectedLinkInstances) {
174             transaction.removeOperationalData(affectedLink);
175         }
176     }
177     
178     private def InstanceIdentifier<Node> nodePath(NodeId nodeId) {
179         val nodeKey = new NodeKey(nodeId);
180         return InstanceIdentifier.builder(NetworkTopology)
181             .child(Topology, topology)
182             .child(Node, nodeKey)
183             .toInstance;
184     }
185     
186     private def InstanceIdentifier<TerminationPoint> tpPath(NodeId nodeId, TpId tpId) {
187         val nodeKey = new NodeKey(nodeId);
188         val tpKey = new TerminationPointKey(tpId)
189         return InstanceIdentifier.builder(NetworkTopology).child(Topology, topology).child(Node, nodeKey).
190             child(TerminationPoint, tpKey).toInstance;
191     }
192     
193     private def InstanceIdentifier<Link> linkPath(Link link) {
194         val linkInstanceId = InstanceIdentifier.builder(NetworkTopology)
195             .child(Topology, topology)
196             .child(Link, link.key)
197             .toInstance;
198         return linkInstanceId;
199     }    
200 }