2 * Copyright (c) 2014 Cisco Systems, Inc. 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
9 package org.opendaylight.openflowplugin.applications.statistics.manager.impl;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
19 import java.util.concurrent.ConcurrentHashMap;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
23 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
24 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
25 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
26 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
27 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
28 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
29 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
30 import org.opendaylight.openflowplugin.applications.statistics.manager.StatNodeRegistration;
31 import org.opendaylight.openflowplugin.applications.statistics.manager.StatPermCollector.StatCapabTypes;
32 import org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManager;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityGroupStats;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeatures;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
48 import org.opendaylight.yangtools.concepts.ListenerRegistration;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.common.QName;
51 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
58 * org.opendaylight.openflowplugin.applications.statistics.manager.impl
60 * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
62 * Created: Aug 28, 2014
64 public class StatNodeRegistrationImpl implements StatNodeRegistration,EntityOwnershipListener {
66 private static final Logger LOG = LoggerFactory.getLogger(StatNodeRegistrationImpl.class);
68 private static final QName ENTITY_QNAME =
69 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.core.general.entity.rev150820.Entity.QNAME;
70 private static final QName ENTITY_NAME = QName.create(ENTITY_QNAME, "name");
72 private final StatisticsManager manager;
73 private ListenerRegistration<?> notifListenerRegistration;
74 //private DataBroker db;
75 private EntityOwnershipListenerRegistration ofListenerRegistration = null;
76 private final Map<NodeId, Boolean> nodeOwnershipState = new ConcurrentHashMap();
79 public StatNodeRegistrationImpl(final StatisticsManager manager, final DataBroker db,
80 final NotificationProviderService notificationService) {
81 this.manager = Preconditions.checkNotNull(manager, "StatisticManager can not be null!");
82 //this.db = Preconditions.checkNotNull(db, "DataBroker can not be null!");
83 Preconditions.checkArgument(notificationService != null, "NotificationProviderService can not be null!");
84 notifListenerRegistration = notificationService.registerNotificationListener(this);
86 if(manager.getOwnershipService() != null) {
87 ofListenerRegistration = manager.getOwnershipService().registerListener("openflow", this);
92 public void close() throws Exception {
94 if (notifListenerRegistration != null) {
96 notifListenerRegistration.close();
98 catch (final Exception e) {
99 LOG.warn("Error by stop FlowCapableNode Notification StatNodeRegistration. Exception {}", e);
101 notifListenerRegistration = null;
104 if (ofListenerRegistration!= null) {
106 ofListenerRegistration.close();
107 } catch (final Exception e) {
108 LOG.warn("Error by stop FlowCapableNode EntityOwnershipListener.", e);
110 ofListenerRegistration = null;
115 public void connectFlowCapableNode(final InstanceIdentifier<SwitchFeatures> keyIdent,
116 final SwitchFeatures data, final InstanceIdentifier<Node> nodeIdent) {
117 Preconditions.checkNotNull(keyIdent, "InstanceIdentifier can not be null!");
118 Preconditions.checkNotNull(data, "SwitchFeatures data for {} can not be null!", keyIdent);
119 Preconditions.checkArgument(( ! keyIdent.isWildcarded()), "InstanceIdentifier is WildCarded!");
121 LOG.trace("STAT-MANAGER - connecting flow capable node {}", nodeIdent);
122 final List<StatCapabTypes> statCapabTypes = new ArrayList<>();
123 Short maxCapTables = Short.valueOf("1");
125 final List<Class<? extends FeatureCapability>> capabilities = data.getCapabilities() != null
126 ? data.getCapabilities() : Collections.<Class<? extends FeatureCapability>> emptyList();
127 for (final Class<? extends FeatureCapability> capability : capabilities) {
128 if (FlowFeatureCapabilityTableStats.class.equals(capability)) {
129 statCapabTypes.add(StatCapabTypes.TABLE_STATS);
130 } else if (FlowFeatureCapabilityFlowStats.class.equals(capability)) {
131 statCapabTypes.add(StatCapabTypes.FLOW_STATS);
132 } else if (FlowFeatureCapabilityGroupStats.class.equals(capability)) {
133 statCapabTypes.add(StatCapabTypes.GROUP_STATS);
134 } else if (FlowFeatureCapabilityPortStats.class.equals(capability)) {
135 statCapabTypes.add(StatCapabTypes.PORT_STATS);
136 } else if (FlowFeatureCapabilityQueueStats.class.equals(capability)) {
137 statCapabTypes.add(StatCapabTypes.QUEUE_STATS);
140 maxCapTables = data.getMaxTables();
142 final Optional<Short> maxTables = Optional.<Short> of(maxCapTables);
143 manager.connectedNodeRegistration(nodeIdent, Collections.unmodifiableList(statCapabTypes), maxTables.get());
147 public void disconnectFlowCapableNode(final InstanceIdentifier<Node> nodeIdent) {
148 Preconditions.checkArgument(nodeIdent != null, "InstanceIdentifier can not be NULL!");
149 Preconditions.checkArgument(( ! nodeIdent.isWildcarded()),
150 "InstanceIdentifier {} is WildCarded!", nodeIdent);
151 LOG.trace("STAT-MANAGER - disconnect flow capable node {}", nodeIdent);
152 manager.disconnectedNodeUnregistration(nodeIdent);
155 private boolean preConfigurationCheck(final NodeId nodeId) {
156 Preconditions.checkNotNull(nodeId, "Node Instance Identifier can not be null!");
157 final Entity entity = getEntity(nodeId);
158 EntityOwnershipService ownershipService = manager.getOwnershipService();
159 if(ownershipService == null) {
160 LOG.error("preConfigurationCheck: EntityOwnershipService is null");
163 Optional<EntityOwnershipState> entityOwnershipStateOptional = ownershipService.getOwnershipState(entity);
164 if(!entityOwnershipStateOptional.isPresent()) { //abset - assume this ofp is owning entity
165 LOG.warn("preConfigurationCheck: Entity state of {} is absent - acting as a non-owner",nodeId.getValue());
168 final EntityOwnershipState entityOwnershipState = entityOwnershipStateOptional.get();
169 if(!(entityOwnershipState.hasOwner() && entityOwnershipState.isOwner())) {
170 LOG.info("preConfigurationCheck: Controller is not the owner of {}",nodeId.getValue());
177 public void onNodeConnectorRemoved(final NodeConnectorRemoved notification) {
182 public void onNodeConnectorUpdated(final NodeConnectorUpdated notification) {
187 public void onNodeRemoved(final NodeRemoved notification) {
188 Preconditions.checkNotNull(notification);
189 final NodeRef nodeRef = notification.getNodeRef();
190 final InstanceIdentifier<?> nodeRefIdent = nodeRef.getValue();
191 final InstanceIdentifier<Node> nodeIdent =
192 nodeRefIdent.firstIdentifierOf(Node.class);
193 if (nodeIdent != null) {
194 LOG.debug("Received onNodeRemoved for node:{} ", nodeIdent);
195 removeOwnership(InstanceIdentifier.keyOf(nodeIdent).getId());
196 disconnectFlowCapableNode(nodeIdent);
201 public void onNodeUpdated(final NodeUpdated notification) {
202 Preconditions.checkNotNull(notification);
203 final FlowCapableNodeUpdated newFlowNode =
204 notification.getAugmentation(FlowCapableNodeUpdated.class);
205 LOG.info("Received onNodeUpdated for node {} ", newFlowNode);
206 if (newFlowNode != null && newFlowNode.getSwitchFeatures() != null) {
207 final NodeRef nodeRef = notification.getNodeRef();
208 final InstanceIdentifier<?> nodeRefIdent = nodeRef.getValue();
209 final InstanceIdentifier<Node> nodeIdent =
210 nodeRefIdent.firstIdentifierOf(Node.class);
212 final InstanceIdentifier<SwitchFeatures> swichFeaturesIdent =
213 nodeIdent.augmentation(FlowCapableNode.class).child(SwitchFeatures.class);
214 final SwitchFeatures switchFeatures = newFlowNode.getSwitchFeatures();
215 connectFlowCapableNode(swichFeaturesIdent, switchFeatures, nodeIdent);
217 //Send group/meter request to get addition details not present in switch feature response.
218 NodeId nodeId = InstanceIdentifier.keyOf(nodeIdent).getId();
219 boolean ownershipState = preConfigurationCheck(nodeId);
220 setNodeOwnership(nodeId, ownershipState);
222 LOG.info("onNodeUpdated: Send group/meter feature request to the device {}",nodeIdent);
223 manager.getRpcMsgManager().getGroupFeaturesStat(nodeRef);
224 manager.getRpcMsgManager().getMeterFeaturesStat(nodeRef);
230 public boolean isFlowCapableNodeOwner(NodeId node) {
231 if(this.nodeOwnershipState.containsKey(node)){
232 return this.nodeOwnershipState.get(node).booleanValue();
239 public void ownershipChanged(EntityOwnershipChange ownershipChange) {
241 YangInstanceIdentifier yId = ownershipChange.getEntity().getId();
242 NodeIdentifierWithPredicates niWPredicates = (NodeIdentifierWithPredicates)yId.getLastPathArgument();
243 Map<QName, Object> keyValMap = niWPredicates.getKeyValues();
244 String nodeIdStr = (String)(keyValMap.get(ENTITY_NAME));
245 BigInteger dpId = new BigInteger(nodeIdStr.split(":")[1]);
246 NodeId nodeId = new NodeId(nodeIdStr);
247 setNodeOwnership(nodeId, ownershipChange.isOwner());
250 private void setNodeOwnership(NodeId node, boolean ownership) {
251 this.nodeOwnershipState.put(node,ownership);
254 private void removeOwnership(NodeId node) {
255 this.nodeOwnershipState.remove(node);
258 private Entity getEntity(NodeId nodeId) {
259 return new Entity("openflow", nodeId.getValue());