Merge "Enable nitpicky mode and fail on warnings"
[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 org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnector;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnectorBuilder;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 public class TerminationPointChangeListenerImpl extends DataTreeChangeListenerImpl<FlowCapableNodeConnector> {
35     private static final Logger LOG = LoggerFactory.getLogger(TerminationPointChangeListenerImpl.class);
36
37     public TerminationPointChangeListenerImpl(final DataBroker dataBroker,
38                                               final OperationProcessor operationProcessor) {
39         super(operationProcessor, dataBroker,
40               InstanceIdentifier.builder(Nodes.class).child(Node.class).child(NodeConnector.class)
41                       .augmentation(FlowCapableNodeConnector.class).build());
42         this.operationProcessor = operationProcessor;
43     }
44
45     @Override
46     public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<FlowCapableNodeConnector>> modifications) {
47         for (DataTreeModification<FlowCapableNodeConnector> modification : modifications) {
48             switch (modification.getRootNode().getModificationType()) {
49                 case WRITE:
50                     processAddedTerminationPoints(modification);
51                     break;
52                 case SUBTREE_MODIFIED:
53                     processUpdatedTerminationPoints(modification);
54                     break;
55                 case DELETE:
56                     processRemovedTerminationPoints(modification);
57                     break;
58                 default:
59                     throw new IllegalArgumentException(
60                             "Unhandled modification type: {}" + modification.getRootNode().getModificationType());
61             }
62         }
63     }
64
65     private void processRemovedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
66         final InstanceIdentifier<FlowCapableNodeConnector> removedNode = modification.getRootPath().getRootIdentifier();
67         final TpId terminationPointId = provideTopologyTerminationPointId(removedNode);
68         final InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
69                 terminationPointId, removedNode);
70
71         if (iiToTopologyTerminationPoint != null) {
72             final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology
73                     .rev131021.network.topology.topology.Node>
74                     node = iiToTopologyTerminationPoint.firstIdentifierOf(
75                     org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network
76                             .topology.topology.Node.class);
77             operationProcessor.enqueueOperation(manager -> {
78                 Optional<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network
79                         .topology.topology.Node>
80                         nodeOptional = Optional.empty();
81                 try {
82                     nodeOptional = Optional.ofNullable(
83                             manager.readFromTransaction(LogicalDatastoreType.OPERATIONAL, node).get().orNull());
84                 } catch (InterruptedException | ExecutionException e) {
85                     LOG.warn("Error occurred when trying to read NodeConnector: {}", e.getMessage());
86                     LOG.debug("Error occurred when trying to read NodeConnector.. ", e);
87                 }
88                 if (nodeOptional.isPresent()) {
89                     TopologyManagerUtil.removeAffectedLinks(terminationPointId, manager, II_TO_TOPOLOGY);
90                     manager.addDeleteOperationToTxChain(LogicalDatastoreType.OPERATIONAL,
91                                                          iiToTopologyTerminationPoint);
92                 }
93             });
94         } else {
95             LOG.debug(
96                     "Instance identifier to inventory wasn't translated to topology while deleting termination point.");
97         }
98     }
99
100     private void processUpdatedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
101         // TODO Auto-generated method stub
102     }
103
104     private void processAddedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
105         final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory = modification.getRootPath()
106                 .getRootIdentifier();
107         TpId terminationPointIdInTopology = provideTopologyTerminationPointId(iiToNodeInInventory);
108         if (terminationPointIdInTopology != null) {
109             InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
110                     terminationPointIdInTopology, iiToNodeInInventory);
111             TerminationPoint point = prepareTopologyTerminationPoint(terminationPointIdInTopology, iiToNodeInInventory);
112             sendToTransactionChain(point, iiToTopologyTerminationPoint);
113             removeLinks(modification.getRootNode().getDataAfter(), point);
114         } else {
115             LOG.debug("Inventory node connector key is null. Data can't be written to topology termination point");
116         }
117     }
118
119     private void removeLinks(final FlowCapableNodeConnector flowCapNodeConnector, final TerminationPoint point) {
120         operationProcessor.enqueueOperation(manager -> {
121             if ((flowCapNodeConnector.getState() != null && flowCapNodeConnector.getState().isLinkDown()) || (
122                     flowCapNodeConnector.getConfiguration() != null && flowCapNodeConnector.getConfiguration()
123                             .isPORTDOWN())) {
124                 TopologyManagerUtil.removeAffectedLinks(point.getTpId(), manager, II_TO_TOPOLOGY);
125             }
126         });
127     }
128
129     private static TerminationPoint prepareTopologyTerminationPoint(final TpId terminationPointIdInTopology,
130                                                                     final
131                                                                     InstanceIdentifier<FlowCapableNodeConnector>
132                                                                             iiToNodeInInventory) {
133         final InventoryNodeConnector inventoryNodeConnector = new InventoryNodeConnectorBuilder()
134                 .setInventoryNodeConnectorRef(
135                         new NodeConnectorRef(iiToNodeInInventory.firstIdentifierOf(NodeConnector.class))).build();
136         final TerminationPointBuilder terminationPointBuilder = new TerminationPointBuilder();
137         terminationPointBuilder.setTpId(terminationPointIdInTopology);
138         terminationPointBuilder.addAugmentation(InventoryNodeConnector.class, inventoryNodeConnector);
139         return terminationPointBuilder.build();
140     }
141
142     private InstanceIdentifier<TerminationPoint> provideIIToTopologyTerminationPoint(
143             final TpId terminationPointIdInTopology,
144             final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
145         NodeId nodeIdInTopology = provideTopologyNodeId(iiToNodeInInventory);
146         if (terminationPointIdInTopology != null && nodeIdInTopology != null) {
147             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology
148                     .rev131021.network.topology.topology.Node>
149                     iiToTopologyNode = provideIIToTopologyNode(nodeIdInTopology);
150             return iiToTopologyNode.builder()
151                     .child(TerminationPoint.class, new TerminationPointKey(terminationPointIdInTopology)).build();
152         } else {
153             LOG.debug(
154                     "Value of termination point ID in topology is null. Instance identifier to topology can't be "
155                             + "built");
156             return null;
157         }
158     }
159
160     private static TpId provideTopologyTerminationPointId(
161             final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
162         NodeConnectorKey inventoryNodeConnectorKey = iiToNodeInInventory.firstKeyOf(NodeConnector.class);
163         if (inventoryNodeConnectorKey != null) {
164             return new TpId(inventoryNodeConnectorKey.getId().getValue());
165         }
166         return null;
167     }
168
169 }