Bump upstreams for Silicon
[genius.git] / fcapsapplication / fcapsapplication-impl / src / main / java / org / opendaylight / genius / fcapsapp / performancecounter / FlowNodeConnectorInventoryTranslatorImpl.java
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. 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.genius.fcapsapp.performancecounter;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.ArrayListMultimap;
13 import com.google.common.collect.Iterables;
14 import com.google.common.collect.Multimap;
15 import com.google.common.collect.Multimaps;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.apache.aries.blueprint.annotation.service.Reference;
20 import org.opendaylight.genius.fcapsapp.FcapsConstants;
21 import org.opendaylight.genius.fcapsapp.portinfo.PortNameMapping;
22 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
23 import org.opendaylight.infrautils.metrics.Counter;
24 import org.opendaylight.infrautils.metrics.Labeled;
25 import org.opendaylight.infrautils.metrics.MetricDescriptor;
26 import org.opendaylight.infrautils.metrics.MetricProvider;
27 import org.opendaylight.mdsal.binding.api.DataBroker;
28 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 @Singleton
41 public class FlowNodeConnectorInventoryTranslatorImpl extends NodeConnectorEventListener<FlowCapableNodeConnector> {
42     private static final Logger LOG = LoggerFactory.getLogger(FlowNodeConnectorInventoryTranslatorImpl.class);
43
44     private static final int STARTUP_LOOP_TICK = 500;
45     private static final int STARTUP_LOOP_MAX_RETRIES = 8;
46
47     private final EntityOwnershipUtils entityOwnershipUtils;
48     private ListenerRegistration<FlowNodeConnectorInventoryTranslatorImpl> dataTreeChangeListenerRegistration;
49
50     private static final String SEPARATOR = ":";
51     private final Labeled<Labeled<Labeled<Counter>>> packetInCounter;
52     private static final InstanceIdentifier<FlowCapableNodeConnector>
53             II_TO_FLOW_CAPABLE_NODE_CONNECTOR = InstanceIdentifier
54             .builder(Nodes.class).child(Node.class).child(NodeConnector.class)
55             .augmentation(FlowCapableNodeConnector.class).build();
56
57     private static Multimap<Long, String> dpnToPortMultiMap = Multimaps
58             .synchronizedListMultimap(ArrayListMultimap.<Long, String>create());
59
60
61     @Inject
62     @SuppressWarnings("checkstyle:IllegalCatch")
63     public FlowNodeConnectorInventoryTranslatorImpl(@Reference final DataBroker dataBroker,
64                                                     final EntityOwnershipUtils entityOwnershipUtils,
65                                                     @Reference MetricProvider metricProvider) {
66         requireNonNull(dataBroker, "DataBroker can not be null!");
67         this.entityOwnershipUtils = entityOwnershipUtils;
68         packetInCounter =  metricProvider.newCounter(MetricDescriptor.builder().anchor(this)
69                 .project("genius").module("fcapsapplication")
70                 .id("entitycounter").build(), "entitytype", "switchid","name");
71         final DataTreeIdentifier<FlowCapableNodeConnector> treeId = DataTreeIdentifier.create(
72                 LogicalDatastoreType.OPERATIONAL, getWildCardPath());
73         try {
74             SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
75             dataTreeChangeListenerRegistration = looper.loopUntilNoException(() -> dataBroker
76                     .registerDataTreeChangeListener(treeId, FlowNodeConnectorInventoryTranslatorImpl.this));
77         } catch (Exception e) {
78             LOG.warn(" FlowNodeConnectorInventoryTranslatorImpl listener registration fail!");
79             LOG.debug("FlowNodeConnectorInventoryTranslatorImpl DataChange listener registration fail ..", e);
80             throw new IllegalStateException(
81                     "FlowNodeConnectorInventoryTranslatorImpl startup fail! System needs restart.", e);
82         }
83     }
84
85     protected InstanceIdentifier<FlowCapableNodeConnector> getWildCardPath() {
86         return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
87                 .augmentation(FlowCapableNodeConnector.class);
88     }
89
90     @PreDestroy
91     @Override
92     public void close() {
93         if (dataTreeChangeListenerRegistration != null) {
94             dataTreeChangeListenerRegistration.close();
95             dataTreeChangeListenerRegistration = null;
96         }
97     }
98
99     @Override
100     public void remove(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector del,
101                        InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
102         Counter counter;
103         if (compareInstanceIdentifierTail(identifier, II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
104             String nodeConnectorIdentifier = getNodeConnectorId(
105                     String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
106             long dataPathId = getDpIdFromPortName(nodeConnectorIdentifier);
107             if (dpnToPortMultiMap.containsKey(dataPathId)) {
108                 LOG.debug("Node Connector {} removed", nodeConnectorIdentifier);
109                 dpnToPortMultiMap.remove(dataPathId, nodeConnectorIdentifier);
110                 counter = packetInCounter.label("OFSwitch").label(String.valueOf(dataPathId)).label("portsperswitch");
111                 counter.decrement();
112                 PortNameMapping.updatePortMap("openflow:" + dataPathId + ":" + del.getName(), nodeConnectorIdentifier,
113                         "DELETE");
114             }
115         }
116     }
117
118     @Override
119     public void update(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector original,
120             FlowCapableNodeConnector update, InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
121         // Don't need to do anything as we are not considering updates here
122     }
123
124     @Override
125     public void add(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector add,
126             InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
127         Counter counter;
128         if (compareInstanceIdentifierTail(identifier, II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
129
130             String nodeConnectorIdentifier = getNodeConnectorId(
131                     String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
132             long dataPathId = getDpIdFromPortName(nodeConnectorIdentifier);
133             if (entityOwnershipUtils.isEntityOwner(FcapsConstants.SERVICE_ENTITY_TYPE,getNodeId(dataPathId))) {
134                 if (!dpnToPortMultiMap.containsEntry(dataPathId, nodeConnectorIdentifier)) {
135                     LOG.debug("Node Connector {} added", nodeConnectorIdentifier);
136                     dpnToPortMultiMap.put(dataPathId, nodeConnectorIdentifier);
137                     counter = packetInCounter.label("OFSwitch")
138                             .label(String.valueOf(dataPathId)).label("portsperswitch");
139                     counter.increment();
140                     PortNameMapping.updatePortMap("openflow:" + dataPathId + ":" + add.getName(),
141                             nodeConnectorIdentifier, "ADD");
142                 } else {
143                     LOG.error("Duplicate Event.Node Connector already added");
144                 }
145             }
146         }
147     }
148
149     private String getNodeConnectorId(String node) {
150         // Uri [_value=openflow:1:1]
151         String[] temp = node.split("=");
152         return temp[1].substring(0, temp[1].length() - 1);
153     }
154
155     private String getNodeId(Long dpnId) {
156         return "openflow:" + dpnId;
157     }
158
159     private boolean compareInstanceIdentifierTail(InstanceIdentifier<?> identifier1,
160             InstanceIdentifier<?> identifier2) {
161         return Iterables.getLast(identifier1.getPathArguments())
162                 .equals(Iterables.getLast(identifier2.getPathArguments()));
163     }
164
165     private long getDpIdFromPortName(String portName) {
166         String dpId = portName.substring(portName.indexOf(SEPARATOR) + 1, portName.lastIndexOf(SEPARATOR));
167         return Long.parseLong(dpId);
168     }
169
170     public void nodeRemovedNotification(String node) {
171         Counter counter;
172         String[] switchId = node.split(":");
173         counter = packetInCounter.label("OFSwitch").label(String.valueOf(switchId[1])).label("portsperswitch");
174         counter.close();
175     }
176 }