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