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