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;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
18 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
19 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
20 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
21 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
22 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
23 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
24 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
25 import org.opendaylight.openflowplugin.applications.statistics.manager.StatNodeRegistration;
26 import org.opendaylight.openflowplugin.applications.statistics.manager.StatPermCollector.StatCapabTypes;
27 import org.opendaylight.openflowplugin.applications.statistics.manager.StatisticsManager;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityGroupStats;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeatures;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
43 import org.opendaylight.yangtools.concepts.ListenerRegistration;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
50 * org.opendaylight.openflowplugin.applications.statistics.manager.impl
52 * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
54 * Created: Aug 28, 2014
56 public class StatNodeRegistrationImpl implements StatNodeRegistration,EntityOwnershipListener {
58 private static final Logger LOG = LoggerFactory.getLogger(StatNodeRegistrationImpl.class);
60 private final StatisticsManager manager;
61 private ListenerRegistration<?> notifListenerRegistration;
62 //private DataBroker db;
63 private EntityOwnershipListenerRegistration ofListenerRegistration = null;
65 public StatNodeRegistrationImpl(final StatisticsManager manager, final DataBroker db,
66 final NotificationProviderService notificationService) {
67 this.manager = Preconditions.checkNotNull(manager, "StatisticManager can not be null!");
68 //this.db = Preconditions.checkNotNull(db, "DataBroker can not be null!");
69 Preconditions.checkArgument(notificationService != null, "NotificationProviderService can not be null!");
70 notifListenerRegistration = notificationService.registerNotificationListener(this);
72 if(manager.getOwnershipService() != null) {
73 ofListenerRegistration = manager.getOwnershipService().registerListener("openflow", this);
78 public void close() throws Exception {
80 if (notifListenerRegistration != null) {
82 notifListenerRegistration.close();
84 catch (final Exception e) {
85 LOG.warn("Error by stop FlowCapableNode Notification StatNodeRegistration. Exception {}", e);
87 notifListenerRegistration = null;
90 if (ofListenerRegistration!= null) {
92 ofListenerRegistration.close();
93 } catch (final Exception e) {
94 LOG.warn("Error by stop FlowCapableNode EntityOwnershipListener.", e);
96 ofListenerRegistration = null;
101 public void connectFlowCapableNode(final InstanceIdentifier<SwitchFeatures> keyIdent,
102 final SwitchFeatures data, final InstanceIdentifier<Node> nodeIdent) {
103 Preconditions.checkNotNull(keyIdent, "InstanceIdentifier can not be null!");
104 Preconditions.checkNotNull(data, "SwitchFeatures data for {} can not be null!", keyIdent);
105 Preconditions.checkArgument(( ! keyIdent.isWildcarded()), "InstanceIdentifier is WildCarded!");
107 LOG.trace("STAT-MANAGER - connecting flow capable node {}", nodeIdent);
108 final List<StatCapabTypes> statCapabTypes = new ArrayList<>();
109 Short maxCapTables = Short.valueOf("1");
111 final List<Class<? extends FeatureCapability>> capabilities = data.getCapabilities() != null
112 ? data.getCapabilities() : Collections.<Class<? extends FeatureCapability>> emptyList();
113 for (final Class<? extends FeatureCapability> capability : capabilities) {
114 if (FlowFeatureCapabilityTableStats.class.equals(capability)) {
115 statCapabTypes.add(StatCapabTypes.TABLE_STATS);
116 } else if (FlowFeatureCapabilityFlowStats.class.equals(capability)) {
117 statCapabTypes.add(StatCapabTypes.FLOW_STATS);
118 } else if (FlowFeatureCapabilityGroupStats.class.equals(capability)) {
119 statCapabTypes.add(StatCapabTypes.GROUP_STATS);
120 } else if (FlowFeatureCapabilityPortStats.class.equals(capability)) {
121 statCapabTypes.add(StatCapabTypes.PORT_STATS);
122 } else if (FlowFeatureCapabilityQueueStats.class.equals(capability)) {
123 statCapabTypes.add(StatCapabTypes.QUEUE_STATS);
126 maxCapTables = data.getMaxTables();
128 final Optional<Short> maxTables = Optional.<Short> of(maxCapTables);
129 manager.connectedNodeRegistration(nodeIdent, Collections.unmodifiableList(statCapabTypes), maxTables.get());
133 public void disconnectFlowCapableNode(final InstanceIdentifier<Node> nodeIdent) {
134 Preconditions.checkArgument(nodeIdent != null, "InstanceIdentifier can not be NULL!");
135 Preconditions.checkArgument(( ! nodeIdent.isWildcarded()),
136 "InstanceIdentifier {} is WildCarded!", nodeIdent);
137 LOG.trace("STAT-MANAGER - disconnect flow capable node {}", nodeIdent);
138 manager.disconnectedNodeUnregistration(nodeIdent);
141 private boolean preConfigurationCheck(final InstanceIdentifier<Node> nodeIdent) {
142 Preconditions.checkNotNull(nodeIdent, "Node Instance Identifier can not be null!");
143 NodeId nodeId = InstanceIdentifier.keyOf(nodeIdent).getId();
144 final Entity entity = new Entity("openflow", nodeId.getValue());
145 EntityOwnershipService ownershipService = manager.getOwnershipService();
146 if(ownershipService == null) {
147 LOG.error("preConfigurationCheck: EntityOwnershipService is null");
150 Optional<EntityOwnershipState> entityOwnershipStateOptional = ownershipService.getOwnershipState(entity);
151 if(!entityOwnershipStateOptional.isPresent()) { //abset - assume this ofp is owning entity
152 LOG.warn("preConfigurationCheck: Entity state of {} is absent - acting as a non-owner",nodeId.getValue());
155 final EntityOwnershipState entityOwnershipState = entityOwnershipStateOptional.get();
156 if(!(entityOwnershipState.hasOwner() && entityOwnershipState.isOwner())) {
157 LOG.info("preConfigurationCheck: Controller is not the owner of {}",nodeId.getValue());
164 public void onNodeConnectorRemoved(final NodeConnectorRemoved notification) {
169 public void onNodeConnectorUpdated(final NodeConnectorUpdated notification) {
174 public void onNodeRemoved(final NodeRemoved notification) {
175 Preconditions.checkNotNull(notification);
176 final NodeRef nodeRef = notification.getNodeRef();
177 final InstanceIdentifier<?> nodeRefIdent = nodeRef.getValue();
178 final InstanceIdentifier<Node> nodeIdent =
179 nodeRefIdent.firstIdentifierOf(Node.class);
180 if (nodeIdent != null) {
181 LOG.debug("Received onNodeRemoved for node:{} ", nodeIdent);
182 disconnectFlowCapableNode(nodeIdent);
187 public void onNodeUpdated(final NodeUpdated notification) {
188 Preconditions.checkNotNull(notification);
189 final FlowCapableNodeUpdated newFlowNode =
190 notification.getAugmentation(FlowCapableNodeUpdated.class);
191 LOG.info("Received onNodeUpdated for node {} ", newFlowNode);
192 if (newFlowNode != null && newFlowNode.getSwitchFeatures() != null) {
193 final NodeRef nodeRef = notification.getNodeRef();
194 final InstanceIdentifier<?> nodeRefIdent = nodeRef.getValue();
195 final InstanceIdentifier<Node> nodeIdent =
196 nodeRefIdent.firstIdentifierOf(Node.class);
198 final InstanceIdentifier<SwitchFeatures> swichFeaturesIdent =
199 nodeIdent.augmentation(FlowCapableNode.class).child(SwitchFeatures.class);
200 final SwitchFeatures switchFeatures = newFlowNode.getSwitchFeatures();
201 connectFlowCapableNode(swichFeaturesIdent, switchFeatures, nodeIdent);
203 //Send group/meter request to get addition details not present in switch feature response.
204 if(preConfigurationCheck(nodeIdent)) {
205 LOG.info("onNodeUpdated: Send group/meter feature request to the device {}",nodeIdent);
206 manager.getRpcMsgManager().getGroupFeaturesStat(nodeRef);
207 manager.getRpcMsgManager().getMeterFeaturesStat(nodeRef);
213 public void ownershipChanged(EntityOwnershipChange ownershipChange) {
214 //I believe the only scenario we need to handle here is
215 // isOwner=false && hasOwner=false. E.g switch is connected to only
216 // one controller and that goes down, all other controller will get
217 // notification about ownership change with the flag set as above.
218 // In this scenario, topology manager should remove the node from
219 // operational data store, so no explict action is required here.