2 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.fcapsapp.performancecounter;
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 java.util.Collection;
16 import java.util.HashMap;
17 import javax.annotation.PreDestroy;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
23 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
24 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.genius.fcapsapp.portinfo.PortNameMapping;
27 import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
32 import org.opendaylight.yangtools.concepts.ListenerRegistration;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 public class FlowNodeConnectorInventoryTranslatorImpl extends NodeConnectorEventListener<FlowCapableNodeConnector> {
39 public static final int STARTUP_LOOP_TICK = 500;
40 public static final int STARTUP_LOOP_MAX_RETRIES = 8;
41 private static final Logger LOG = LoggerFactory.getLogger(FlowNodeConnectorInventoryTranslatorImpl.class);
42 private final EntityOwnershipService entityOwnershipService;
43 private final DataBroker dataBroker;
44 private ListenerRegistration<FlowNodeConnectorInventoryTranslatorImpl> dataTreeChangeListenerRegistration;
46 public static final String SEPARATOR = ":";
47 private final PMAgent agent;
49 private static final InstanceIdentifier<FlowCapableNodeConnector>
50 II_TO_FLOW_CAPABLE_NODE_CONNECTOR = InstanceIdentifier
51 .builder(Nodes.class).child(Node.class).child(NodeConnector.class)
52 .augmentation(FlowCapableNodeConnector.class).build();
54 private static Multimap<Long, String> dpnToPortMultiMap = Multimaps
55 .synchronizedListMultimap(ArrayListMultimap.<Long, String>create());
57 private static HashMap<String, String> nodeConnectorCountermap = new HashMap<>();
60 @SuppressWarnings("checkstyle:IllegalCatch")
61 public FlowNodeConnectorInventoryTranslatorImpl(final DataBroker dataBroker,
62 final EntityOwnershipService entityOwnershipService, final PMAgent agent) {
63 super(FlowCapableNodeConnector.class);
64 this.dataBroker = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
65 this.entityOwnershipService = entityOwnershipService;
67 final DataTreeIdentifier<FlowCapableNodeConnector> treeId = new DataTreeIdentifier<>(
68 LogicalDatastoreType.OPERATIONAL, getWildCardPath());
70 SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
71 dataTreeChangeListenerRegistration = looper.loopUntilNoException(() -> dataBroker
72 .registerDataTreeChangeListener(treeId, FlowNodeConnectorInventoryTranslatorImpl.this));
73 } catch (Exception e) {
74 LOG.warn(" FlowNodeConnectorInventoryTranslatorImpl listener registration fail!");
75 LOG.debug("FlowNodeConnectorInventoryTranslatorImpl DataChange listener registration fail ..", e);
76 throw new IllegalStateException(
77 "FlowNodeConnectorInventoryTranslatorImpl startup fail! System needs restart.", e);
81 protected InstanceIdentifier<FlowCapableNodeConnector> getWildCardPath() {
82 return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
83 .augmentation(FlowCapableNodeConnector.class);
89 if (dataTreeChangeListenerRegistration != null) {
90 dataTreeChangeListenerRegistration.close();
91 dataTreeChangeListenerRegistration = null;
96 public void remove(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector del,
97 InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
98 if (compareInstanceIdentifierTail(identifier, II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
99 String nodeConnectorIdentifier = getNodeConnectorId(
100 String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
101 long dataPathId = getDpIdFromPortName(nodeConnectorIdentifier);
102 if (dpnToPortMultiMap.containsKey(dataPathId)) {
103 LOG.debug("Node Connector {} removed", nodeConnectorIdentifier);
104 dpnToPortMultiMap.remove(dataPathId, nodeConnectorIdentifier);
105 sendNodeConnectorUpdation(dataPathId);
106 PortNameMapping.updatePortMap("openflow:" + dataPathId + ":" + del.getName(), nodeConnectorIdentifier,
113 public void update(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector original,
114 FlowCapableNodeConnector update, InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
115 if (compareInstanceIdentifierTail(identifier, II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
116 // Don't need to do anything as we are not considering updates here
117 String nodeConnectorIdentifier = getNodeConnectorId(
118 String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
119 long dataPathId = getDpIdFromPortName(nodeConnectorIdentifier);
120 if (isNodeOwner(getNodeId(dataPathId))) {
121 boolean originalPortStatus = original.getConfiguration().isPORTDOWN();
122 boolean updatePortStatus = update.getConfiguration().isPORTDOWN();
124 if (updatePortStatus) {
125 // port has gone down
126 LOG.debug("Node Connector {} updated port is down", nodeConnectorIdentifier);
127 } else if (originalPortStatus) {
129 LOG.debug("Node Connector {} updated port is up", nodeConnectorIdentifier);
136 public void add(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector add,
137 InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
138 if (compareInstanceIdentifierTail(identifier, II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
140 String nodeConnectorIdentifier = getNodeConnectorId(
141 String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
142 long dataPathId = getDpIdFromPortName(nodeConnectorIdentifier);
143 if (isNodeOwner(getNodeId(dataPathId))) {
144 if (!dpnToPortMultiMap.containsEntry(dataPathId, nodeConnectorIdentifier)) {
145 LOG.debug("Node Connector {} added", nodeConnectorIdentifier);
146 dpnToPortMultiMap.put(dataPathId, nodeConnectorIdentifier);
147 sendNodeConnectorUpdation(dataPathId);
148 PortNameMapping.updatePortMap("openflow:" + dataPathId + ":" + add.getName(),
149 nodeConnectorIdentifier, "ADD");
151 LOG.error("Duplicate Event.Node Connector already added");
157 private String getNodeConnectorId(String node) {
158 // Uri [_value=openflow:1:1]
159 String[] temp = node.split("=");
160 return temp[1].substring(0, temp[1].length() - 1);
163 private String getNodeId(Long dpnId) {
164 return "openflow:" + dpnId;
168 * Method checks if *this* instance of controller is owner of the given
173 * @return True if owner, else false
175 public boolean isNodeOwner(String nodeId) {
176 Entity entity = new Entity("openflow", nodeId);
177 return this.entityOwnershipService.getOwnershipState(entity).transform(EntityOwnershipState::isOwner).or(false);
180 private boolean compareInstanceIdentifierTail(InstanceIdentifier<?> identifier1,
181 InstanceIdentifier<?> identifier2) {
182 return Iterables.getLast(identifier1.getPathArguments())
183 .equals(Iterables.getLast(identifier2.getPathArguments()));
186 private long getDpIdFromPortName(String portName) {
187 String dpId = portName.substring(portName.indexOf(SEPARATOR) + 1, portName.lastIndexOf(SEPARATOR));
188 return Long.parseLong(dpId);
191 private void sendNodeConnectorUpdation(Long dpnId) {
192 Collection<String> portname = dpnToPortMultiMap.get(dpnId);
193 String nodeListPortsCountStr = "dpnId_" + dpnId + "_NumberOfOFPorts";
194 String counterkey = "NumberOfOFPorts:" + nodeListPortsCountStr;
196 if (!portname.isEmpty()) {
197 nodeConnectorCountermap.put(counterkey, "" + portname.size());
199 nodeConnectorCountermap.remove(counterkey);
201 LOG.debug("NumberOfOFPorts:" + nodeListPortsCountStr + " portlistsize " + portname.size());
202 agent.connectToPMAgentForNOOfPorts(nodeConnectorCountermap);