6831af0bcb6648222a97c0c4a87a19762b364a86
[openflowplugin.git] / applications / topology-manager / src / main / java / org / opendaylight / openflowplugin / applications / topology / manager / TerminationPointChangeListenerImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowplugin.applications.topology.manager;
9
10 import java.util.Collection;
11 import java.util.Optional;
12 import java.util.concurrent.ExecutionException;
13 import javax.annotation.Nonnull;
14 import javax.annotation.PreDestroy;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.apache.aries.blueprint.annotation.service.Reference;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.binding.api.DataTreeModification;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnector;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnectorBuilder;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 @Singleton
39 public class TerminationPointChangeListenerImpl extends DataTreeChangeListenerImpl<FlowCapableNodeConnector> {
40     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointChangeListenerImpl.class);
41
42     @Inject
43     public TerminationPointChangeListenerImpl(@Reference final DataBroker dataBroker,
44                                               final OperationProcessor operationProcessor) {
45         super(operationProcessor, dataBroker,
46               InstanceIdentifier.builder(Nodes.class).child(Node.class).child(NodeConnector.class)
47                       .augmentation(FlowCapableNodeConnector.class).build());
48         this.operationProcessor = operationProcessor;
49     }
50
51     @Override
52     public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<FlowCapableNodeConnector>> modifications) {
53         for (DataTreeModification<FlowCapableNodeConnector> modification : modifications) {
54             switch (modification.getRootNode().getModificationType()) {
55                 case WRITE:
56                     processAddedTerminationPoints(modification);
57                     break;
58                 case SUBTREE_MODIFIED:
59                     processUpdatedTerminationPoints(modification);
60                     break;
61                 case DELETE:
62                     processRemovedTerminationPoints(modification);
63                     break;
64                 default:
65                     throw new IllegalArgumentException(
66                             "Unhandled modification type: {}" + modification.getRootNode().getModificationType());
67             }
68         }
69     }
70
71     @Override
72     @PreDestroy
73     public void close() throws Exception {
74         super.close();
75     }
76
77     private void processRemovedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
78         final InstanceIdentifier<FlowCapableNodeConnector> removedNode = modification.getRootPath().getRootIdentifier();
79         final TpId terminationPointId = provideTopologyTerminationPointId(removedNode);
80         final InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
81                 terminationPointId, removedNode);
82
83         if (iiToTopologyTerminationPoint != null) {
84             final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology
85                     .rev131021.network.topology.topology.Node>
86                     node = iiToTopologyTerminationPoint.firstIdentifierOf(
87                     org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network
88                             .topology.topology.Node.class);
89             operationProcessor.enqueueOperation(manager -> {
90                 Optional<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network
91                         .topology.topology.Node>
92                         nodeOptional = Optional.empty();
93                 try {
94                     nodeOptional = manager.readFromTransaction(LogicalDatastoreType.OPERATIONAL, node).get();
95                 } catch (InterruptedException | ExecutionException e) {
96                     LOG.warn("Error occurred when trying to read NodeConnector: {}", e.getMessage());
97                     LOG.debug("Error occurred when trying to read NodeConnector.. ", e);
98                 }
99                 if (nodeOptional.isPresent()) {
100                     TopologyManagerUtil.removeAffectedLinks(terminationPointId, manager, II_TO_TOPOLOGY);
101                     manager.addDeleteOperationToTxChain(LogicalDatastoreType.OPERATIONAL,
102                                                          iiToTopologyTerminationPoint);
103                 }
104             });
105         } else {
106             LOG.debug(
107                     "Instance identifier to inventory wasn't translated to topology while deleting termination point.");
108         }
109     }
110
111     private void processUpdatedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
112         // TODO Auto-generated method stub
113     }
114
115     private void processAddedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
116         final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory = modification.getRootPath()
117                 .getRootIdentifier();
118         TpId terminationPointIdInTopology = provideTopologyTerminationPointId(iiToNodeInInventory);
119         if (terminationPointIdInTopology != null) {
120             InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
121                     terminationPointIdInTopology, iiToNodeInInventory);
122             TerminationPoint point = prepareTopologyTerminationPoint(terminationPointIdInTopology, iiToNodeInInventory);
123             sendToTransactionChain(point, iiToTopologyTerminationPoint);
124             removeLinks(modification.getRootNode().getDataAfter(), point);
125         } else {
126             LOG.debug("Inventory node connector key is null. Data can't be written to topology termination point");
127         }
128     }
129
130     private void removeLinks(final FlowCapableNodeConnector flowCapNodeConnector, final TerminationPoint point) {
131         operationProcessor.enqueueOperation(manager -> {
132             if (flowCapNodeConnector.getState() != null && flowCapNodeConnector.getState().isLinkDown()
133                     || flowCapNodeConnector.getConfiguration() != null
134                         && flowCapNodeConnector.getConfiguration().isPORTDOWN()) {
135                 TopologyManagerUtil.removeAffectedLinks(point.getTpId(), manager, II_TO_TOPOLOGY);
136             }
137         });
138     }
139
140     private static TerminationPoint prepareTopologyTerminationPoint(final TpId terminationPointIdInTopology,
141                                                                     final
142                                                                     InstanceIdentifier<FlowCapableNodeConnector>
143                                                                             iiToNodeInInventory) {
144         final InventoryNodeConnector inventoryNodeConnector = new InventoryNodeConnectorBuilder()
145                 .setInventoryNodeConnectorRef(
146                         new NodeConnectorRef(iiToNodeInInventory.firstIdentifierOf(NodeConnector.class))).build();
147         final TerminationPointBuilder terminationPointBuilder = new TerminationPointBuilder();
148         terminationPointBuilder.setTpId(terminationPointIdInTopology);
149         terminationPointBuilder.addAugmentation(InventoryNodeConnector.class, inventoryNodeConnector);
150         return terminationPointBuilder.build();
151     }
152
153     private InstanceIdentifier<TerminationPoint> provideIIToTopologyTerminationPoint(
154             final TpId terminationPointIdInTopology,
155             final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
156         NodeId nodeIdInTopology = provideTopologyNodeId(iiToNodeInInventory);
157         if (terminationPointIdInTopology != null && nodeIdInTopology != null) {
158             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology
159                     .rev131021.network.topology.topology.Node>
160                     iiToTopologyNode = provideIIToTopologyNode(nodeIdInTopology);
161             return iiToTopologyNode.builder()
162                     .child(TerminationPoint.class, new TerminationPointKey(terminationPointIdInTopology)).build();
163         } else {
164             LOG.debug(
165                     "Value of termination point ID in topology is null. Instance identifier to topology can't be "
166                             + "built");
167             return null;
168         }
169     }
170
171     private static TpId provideTopologyTerminationPointId(
172             final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
173         NodeConnectorKey inventoryNodeConnectorKey = iiToNodeInInventory.firstKeyOf(NodeConnector.class);
174         if (inventoryNodeConnectorKey != null) {
175             return new TpId(inventoryNodeConnectorKey.getId().getValue());
176         }
177         return null;
178     }
179
180 }