Fix transaction manager closing.
[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 javax.annotation.Nonnull;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
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, final OperationProcessor operationProcessor) {
38         super(operationProcessor, dataBroker, InstanceIdentifier.builder(Nodes.class).child(Node.class)
39                 .child(NodeConnector.class).augmentation(FlowCapableNodeConnector.class).build());
40         this.operationProcessor = operationProcessor;
41     }
42
43     @Override
44     public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<FlowCapableNodeConnector>> modifications) {
45         for (DataTreeModification<FlowCapableNodeConnector> modification : modifications) {
46             switch (modification.getRootNode().getModificationType()) {
47                 case WRITE:
48                     processAddedTerminationPoints(modification);
49                     break;
50                 case SUBTREE_MODIFIED:
51                     processUpdatedTerminationPoints(modification);
52                     break;
53                 case DELETE:
54                     processRemovedTerminationPoints(modification);
55                     break;
56                 default:
57                     throw new IllegalArgumentException("Unhandled modification type: {}" +
58                             modification.getRootNode().getModificationType());
59             }
60         }
61     }
62
63     private void processRemovedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
64         final InstanceIdentifier<FlowCapableNodeConnector> removedNode = modification.getRootPath().getRootIdentifier();
65         final TpId terminationPointId = provideTopologyTerminationPointId(removedNode);
66         final InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
67                 terminationPointId, removedNode);
68
69         if (iiToTopologyTerminationPoint != null) {
70             final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> node = iiToTopologyTerminationPoint.firstIdentifierOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node.class);
71             operationProcessor.enqueueOperation(manager -> {
72                 Optional<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> nodeOptional = Optional.empty();
73                 try {
74                     nodeOptional = Optional.ofNullable(
75                             manager.readFromTransaction(LogicalDatastoreType.OPERATIONAL, node).checkedGet().orNull());
76                 } catch (ReadFailedException e) {
77                     LOG.warn("Error occurred when trying to read NodeConnector: {}", e.getMessage());
78                     LOG.debug("Error occurred when trying to read NodeConnector.. ", e);
79                 }
80                 if (nodeOptional.isPresent()) {
81                     TopologyManagerUtil.removeAffectedLinks(terminationPointId, manager, II_TO_TOPOLOGY);
82                     manager.addDeleteOperationTotTxChain(LogicalDatastoreType.OPERATIONAL, iiToTopologyTerminationPoint);
83                 }
84             });
85         } else {
86             LOG.debug("Instance identifier to inventory wasn't translated to topology while deleting termination point.");
87         }
88     }
89
90     private void processUpdatedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
91         // TODO Auto-generated method stub
92     }
93
94     private void processAddedTerminationPoints(final DataTreeModification<FlowCapableNodeConnector> modification) {
95         final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory = modification.getRootPath().getRootIdentifier();
96         TpId terminationPointIdInTopology = provideTopologyTerminationPointId(iiToNodeInInventory);
97         if (terminationPointIdInTopology != null) {
98             InstanceIdentifier<TerminationPoint> iiToTopologyTerminationPoint = provideIIToTopologyTerminationPoint(
99                     terminationPointIdInTopology, iiToNodeInInventory);
100             TerminationPoint point = prepareTopologyTerminationPoint(terminationPointIdInTopology, iiToNodeInInventory);
101             sendToTransactionChain(point, iiToTopologyTerminationPoint);
102             removeLinks(modification.getRootNode().getDataAfter(), point);
103         } else {
104             LOG.debug("Inventory node connector key is null. Data can't be written to topology termination point");
105         }
106     }
107
108     private void removeLinks(final FlowCapableNodeConnector flowCapNodeConnector, final TerminationPoint point) {
109         operationProcessor.enqueueOperation(manager -> {
110             if ((flowCapNodeConnector.getState() != null && flowCapNodeConnector.getState().isLinkDown())
111                     || (flowCapNodeConnector.getConfiguration() != null && flowCapNodeConnector.getConfiguration().isPORTDOWN())) {
112                 TopologyManagerUtil.removeAffectedLinks(point.getTpId(), manager, II_TO_TOPOLOGY);
113             }
114         });
115     }
116
117     private static TerminationPoint prepareTopologyTerminationPoint(final TpId terminationPointIdInTopology,
118                                                                     final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
119         final InventoryNodeConnector inventoryNodeConnector = new InventoryNodeConnectorBuilder()
120                 .setInventoryNodeConnectorRef(new NodeConnectorRef(iiToNodeInInventory.firstIdentifierOf(NodeConnector.class))).build();
121         final TerminationPointBuilder terminationPointBuilder = new TerminationPointBuilder();
122         terminationPointBuilder.setTpId(terminationPointIdInTopology);
123         terminationPointBuilder.addAugmentation(InventoryNodeConnector.class, inventoryNodeConnector);
124         return terminationPointBuilder.build();
125     }
126
127     private InstanceIdentifier<TerminationPoint> provideIIToTopologyTerminationPoint(final TpId terminationPointIdInTopology,
128                                                                                      final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
129         NodeId nodeIdInTopology = provideTopologyNodeId(iiToNodeInInventory);
130         if (terminationPointIdInTopology != null && nodeIdInTopology != null) {
131             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node> iiToTopologyNode = provideIIToTopologyNode(nodeIdInTopology);
132             return iiToTopologyNode.builder().child(TerminationPoint.class, new TerminationPointKey(terminationPointIdInTopology)).build();
133         } else {
134             LOG.debug("Value of termination point ID in topology is null. Instance identifier to topology can't be built");
135             return null;
136         }
137     }
138
139     private static TpId provideTopologyTerminationPointId(final InstanceIdentifier<FlowCapableNodeConnector> iiToNodeInInventory) {
140         NodeConnectorKey inventoryNodeConnectorKey = iiToNodeInInventory.firstKeyOf(NodeConnector.class);
141         if (inventoryNodeConnectorKey != null) {
142             return new TpId(inventoryNodeConnectorKey.getId().getValue());
143         }
144         return null;
145     }
146
147 }