import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
}
verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, statsIpv4Match.getIpv4Source());
}
+ } else if (statsLayer3Match instanceof ArpMatch && storedLayer3Match instanceof ArpMatch) {
+ verdict = arpMatchEquals((ArpMatch)statsLayer3Match, (ArpMatch)storedLayer3Match);
} else {
final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
if (nullCheckOut != null) {
return verdict;
}
+ static boolean arpMatchEquals(final ArpMatch statsArpMatch, final ArpMatch storedArpMatch) {
+
+ Integer statsOp = statsArpMatch.getArpOp();
+ Integer storedOp = storedArpMatch.getArpOp();
+
+ Boolean nullCheck = checkNullValues(statsOp, storedOp);
+ if (nullCheck != null) {
+ if (nullCheck == false) {
+ return false;
+ }
+ } else if (!statsOp.equals(storedOp)) {
+ return false;
+ }
+
+ Ipv4Prefix statsIp = statsArpMatch.getArpSourceTransportAddress();
+ Ipv4Prefix storedIp = storedArpMatch.getArpSourceTransportAddress();
+ if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
+ return false;
+ }
+
+ statsIp = statsArpMatch.getArpTargetTransportAddress();
+ storedIp = storedArpMatch.getArpTargetTransportAddress();
+ if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
+ return false;
+ }
+
+ MacAddressFilter statsMac = statsArpMatch.getArpSourceHardwareAddress();
+ MacAddressFilter storedMac = storedArpMatch.getArpSourceHardwareAddress();
+ if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
+ return false;
+ }
+
+ statsMac = statsArpMatch.getArpTargetHardwareAddress();
+ storedMac = storedArpMatch.getArpTargetHardwareAddress();
+ if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
+ return false;
+ }
+
+ return true;
+ }
+
/**
* TODO: why don't we use the default Ipv4Prefix.equals()?
import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginTimer;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceReplyProcessor;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
* Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
public interface DeviceContext extends AutoCloseable,
- OpenFlowPluginTimer,
DeviceReplyProcessor,
- PortNumberCache {
+ PortNumberCache,
+ XidSequencer {
+
+ void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
/**
* distinguished device context states
/**
* Method creates put operation using provided data in underlying transaction chain.
*/
- <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store, final InstanceIdentifier<T> path, final T data);
+ <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store, final InstanceIdentifier<T> path, final T data) throws Exception;
/**
* Method creates delete operation for provided path in underlying transaction chain.
*/
- <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path);
+ <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path) throws Exception;
/**
* Method submits Transaction to DataStore.
*/
Timeout getBarrierTaskTimeout();
- /**
- * Sets notification service
- *
- * @param notificationService
- */
- void setNotificationService(NotificationService notificationService);
-
void setNotificationPublishService(NotificationPublishService notificationPublishService);
MessageSpy getMessageSpy();
- /**
- * Method sets reference to handler used for cleanup after device context about to be closed.
- */
- void addDeviceContextClosedHandler(DeviceTerminationPhaseHandler deviceContextClosedHandler);
-
MultiMsgCollector getMultiMsgCollector(final RequestContext<List<MultipartReply>> requestContext);
- /**
- * Method is reserved unique XID for Device Message.
- * Attention: OFJava expect the message, otherwise OutboundQueue could stop working.
- * @return Reserved XID
- */
- Long reservedXidForDeviceMessage();
-
/**
* indicates that device context is fully published (e.g.: packetIn messages should be passed)
*/
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.translator.TranslatorLibrarian;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
/**
* This interface is responsible for instantiating DeviceContext and
public interface DeviceManager extends DeviceConnectedHandler, DeviceDisconnectedHandler, DeviceLifecycleSupervisor,
DeviceInitializationPhaseHandler, DeviceTerminationPhaseHandler, TranslatorLibrarian, AutoCloseable {
- /**
- * Sets notification receiving service
- *
- * @param notificationService
- */
- void setNotificationService(NotificationService notificationService);
-
/**
* Sets notification publish service
*
* invoked after all services injected
*/
void initialize();
+
+ /**
+ * Returning device context from map maintained in device manager
+ * This prevent to send whole device context to another context
+ * If device context not exists for nodeId it will return null
+ * @param nodeId
+ * @return device context or null
+ */
+ DeviceContext getDeviceContextFromNodeId(NodeId nodeId);
+
+ void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.device;
+
+/**
+ * Reserves unique XID for Device Messages.
+ */
+public interface XidSequencer {
+
+ /**
+ * Method reserve unique XID for Device Message.
+ * Attention: OFJava expect the message, otherwise OutboundQueue could stop working.
+ * @return Reserved XID
+ */
+ Long reserveXidForDeviceMessage();
+}
* Method is used to propagate information about established connection with device.
* It propagates connected device's connection context.
*/
- void deviceConnected(ConnectionContext connectionContext) throws Exception;
+ boolean deviceConnected(ConnectionContext connectionContext) throws Exception;
}
import javax.annotation.CheckForNull;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
/**
* openflowplugin-api
/**
* Method represents an initialization cycle for {@link DeviceContext} preparation for use.
*
- * @param deviceContext
+ * @param nodeId
* @throws Exception - needs to be catch in ConnectionHandler implementation
*/
- void onDeviceContextLevelUp(@CheckForNull DeviceContext deviceContext) throws Exception;
+ void onDeviceContextLevelUp(@CheckForNull NodeId nodeId) throws Exception;
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+
+/**
+ * This API is for all listeners who wish to know about device context in cluster
+ */
+public interface DeviceContextChangeListener {
+
+ /**
+ * Notification about start phase in device context, right after successful handshake
+ * @param nodeId
+ * @param success or failure
+ */
+ void deviceStartInitializationDone(final NodeId nodeId, final boolean success);
+
+ /**
+ * Notification about start phase in device context, after all other contexts initialized properly
+ * @param nodeId
+ * @param success
+ */
+ void deviceInitializationDone(final NodeId nodeId, final boolean success);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import io.netty.util.Timeout;
+import io.netty.util.TimerTask;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+import javax.annotation.Nonnull;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This class is a binder between all managers
+ * Should be defined in OpenFlowPluginProviderImpl
+ */
+public interface LifecycleConductor {
+
+ /**
+ * Returns device context from device manager device contexts maps
+ * @param nodeId node identification
+ * @return null if context doesn't exists
+ */
+ DeviceContext getDeviceContext(final NodeId nodeId);
+
+ /**
+ * Registers ont time listener for notify when services rpc, statistics are done stop or start
+ * @param manager service change listener
+ * @param nodeId node identification
+ */
+ void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId);
+
+ /**
+ * Returns device of version
+ * @param nodeId node identification
+ * @return null if device context doesn't exists
+ */
+ Short gainVersionSafely(final NodeId nodeId);
+
+ /**
+ * Set new timeout for {@link io.netty.util.HashedWheelTimer}
+ * @param task timer task
+ * @param delay delay
+ * @param unit time unit
+ * @return new timeout
+ */
+ Timeout newTimeout(@Nonnull TimerTask task, long delay, @Nonnull TimeUnit unit);
+
+ /**
+ * Returns message intelligence agency
+ * @return MessageIntelligenceAgency set by constructor
+ */
+ MessageIntelligenceAgency getMessageIntelligenceAgency();
+
+ /**
+ * Interrupt connection for the node
+ * @param nodeId node identification
+ */
+ void closeConnection(final NodeId nodeId);
+
+ /**
+ * Setter for device manager once set it cant be unset or overwritten
+ * @param deviceManager should be set in OpenFlowPluginProviderImpl
+ */
+ void setSafelyDeviceManager(final DeviceManager deviceManager);
+
+ /**
+ * Xid from outboundqueue
+ * @param nodeId
+ * @return
+ */
+ Long reserveXidForDeviceMessage(final NodeId nodeId);
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+
+/**
+ * This API is for all listeners who wish to know about role change in cluster
+ */
+public interface RoleChangeListener {
+
+ /**
+ * Notification when initialization for role context is done
+ * @param nodeId
+ * @param success or failure
+ */
+ void roleInitializationDone(final NodeId nodeId, final boolean success);
+
+ /**
+ * Notification when the role change on device is done
+ * @param nodeId
+ * @param success
+ * @param newRole
+ * @param initializationPhase
+ */
+ void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * This API is defined for listening when services (Statistics and RPCs) are fully stopped
+ * or fully started. Role manager use it for unregister tx entity on shutdown when all is stopped.
+ */
+public interface ServiceChangeListener {
+
+ /**
+ * Notification when services (rpc, statistics) are started or stopped working
+ * @param nodeId
+ * @param success
+ */
+ void servicesChangeDone(NodeId nodeId, boolean success);
+
+}
+++ /dev/null
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.api.openflow.role;
-
-import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-
-/**
- * Double candidate aproach brings protected role change for all node cluster instances.
- *
- * Created by kramesha on 9/19/15.
- */
-public interface RoleChangeListener extends AutoCloseable {
-
- /**
- * Method has to be called from MainCandidate Leaderhip notification {@link OfpRole#BECOMEMASTER}
- * It locks any MainCandidate changes and it registrates TxCandidate to Cluster.
- */
- void onDeviceTryToTakeClusterLeadership();
-
- /**
- * Method has to be called from TxCandidate Leadership notification {@link OfpRole#BECOMEMASTER}
- * and propagate {@link OfpRole#BECOMEMASTER} to device. When device accepts new role, it has to
- * notifies whole DeviceContext suite to take Leadership responsibility
- */
- void onDeviceTakeClusterLeadership();
-
- /**
- * Method has to be called from MainCandidate Leadership notification {@link OfpRole#BECOMESLAVE}
- * It locks any MainCandidate and TxCandidate changes and it starts propagate LostClusterLeadership
- * to Device and whole DeviceContext suite.
- */
- void onDeviceLostClusterLeadership();
-
- /**
- * We need to know when the candidate is registrated or in close process
- * @return true/false
- */
- boolean isMainCandidateRegistered();
-
- /**
- * We need to know when the candidate is registrated or in close process
- * @return true/false
- */
- boolean isTxCandidateRegistered();
-
- Entity getEntity();
-
- Entity getTxEntity();
-
- DeviceState getDeviceState();
-
- @Override
- void close();
-}
*/
package org.opendaylight.openflowplugin.api.openflow.role;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
+
+import javax.annotation.Nonnull;
/**
- * Created by kramesha on 9/12/15.
+ * Rewrote whole role context to prevent errors to change role on cluster
*/
-public interface RoleContext extends RoleChangeListener, RequestContextStack {
+public interface RoleContext extends RequestContextStack, AutoCloseable {
/**
* Initialization method is responsible for a registration of
* {@link org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService}
* returns Role which has to be applied for responsible Device Context suite. Any Exception
* state has to close Device connection channel.
+ * @return true if initialization done ok
*/
- void initializationRoleContext();
+ boolean initialization();
/**
- * Termination method is responsible for an unregistrion of
+ * Termination method is responsible for an unregistration of
* {@link org.opendaylight.controller.md.sal.common.api.clustering.Entity} and listener
* for notification from service
* {@link org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService}
* returns notification "Someone else take Leadership" or "I'm last"
* and we need to clean Oper. DS.
*/
- void terminationRoleContext();
+ void unregisterAllCandidates();
- @Override
- void close();
+ /**
+ * Setter for sal role service
+ * @param salRoleService
+ */
+ void setSalRoleService(@Nonnull final SalRoleService salRoleService);
+
+ /**
+ * Getter for sal role service
+ * @return
+ */
+ SalRoleService getSalRoleService();
+
+ /**
+ * Getter for main entity
+ * @return
+ */
+ Entity getEntity();
+
+ /**
+ * Getter for tx entity
+ * @return
+ */
+ Entity getTxEntity();
+
+ /**
+ * Actual nodeId
+ * @return
+ */
+ NodeId getNodeId();
+
+ /**
+ * Returns true if main entity is registered
+ * @return
+ */
+ boolean isMainCandidateRegistered();
+
+ /**
+ * Returns true if tx entity is registered
+ * @return
+ */
+ boolean isTxCandidateRegistered();
+
+ /**
+ * Register candidate depending on parameter
+ * @param entity
+ * @return true is registration was successful
+ */
+ boolean registerCandidate(final Entity entity);
- DeviceContext getDeviceContext();
+ /**
+ * Unregister candidate depending on parameter
+ * @param entity
+ * @return true is registration was successful
+ */
+ boolean unregisterCandidate(final Entity entity);
- OfpRole getClusterRole();
+ /**
+ * Returns true if we hold both registrations
+ * @return
+ */
+ boolean isMaster();
+ @Override
+ void close();
}
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
/**
* Created by kramesha on 8/31/15.
*/
public interface RoleManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable,
DeviceTerminationPhaseHandler {
- public static final String ENTITY_TYPE = "openflow";
- public static final String TX_ENTITY_TYPE = "ofTransaction";
+ String ENTITY_TYPE = "openflow";
+ String TX_ENTITY_TYPE = "ofTransaction";
+
+ /**
+ * Adding listener to by notified for role changes
+ * API for listener {@link RoleChangeListener}
+ * @param roleChangeListener
+ */
+ void addRoleChangeListener(RoleChangeListener roleChangeListener);
+
}
<S extends RpcService> S lookupRpcService(Class<S> serviceClass);
<S extends RpcService> void unregisterRpcServiceImplementation(Class<S> serviceClass);
- void registerStatCompatibilityServices();
-
@Override
void close();
}
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
/**
* The RPC Manager will maintain an RPC Context for each online switch. RPC context for device is created when
- * {@link org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler#onDeviceContextLevelUp(org.opendaylight.openflowplugin.api.openflow.device.DeviceContext)}
+ * {@link org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler#onDeviceContextLevelUp(NodeId)}
* is called.
* <p>
* Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
public interface RpcManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable, DeviceTerminationPhaseHandler {
- void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
-
- void setNotificationPublishService(NotificationPublishService notificationPublishService);
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timeout;
+import io.netty.util.TimerTask;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.DeviceContextChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ */
+public final class LifecycleConductorImpl implements LifecycleConductor, RoleChangeListener, DeviceContextChangeListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LifecycleConductorImpl.class);
+ private static final int TICKS_PER_WHEEL = 500;
+ private static final long TICK_DURATION = 10; // 0.5 sec.
+
+ private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
+ private DeviceManager deviceManager;
+ private final MessageIntelligenceAgency messageIntelligenceAgency;
+ private ConcurrentHashMap<NodeId, ServiceChangeListener> serviceChangeListeners = new ConcurrentHashMap<>();
+
+ public LifecycleConductorImpl(final MessageIntelligenceAgency messageIntelligenceAgency) {
+ Preconditions.checkNotNull(messageIntelligenceAgency);
+ this.messageIntelligenceAgency = messageIntelligenceAgency;
+ }
+
+ public void setSafelyDeviceManager(final DeviceManager deviceManager) {
+ if (this.deviceManager == null) {
+ this.deviceManager = deviceManager;
+ }
+ }
+
+ public void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId){
+ LOG.debug("Listener {} for service change for node {} registered.", manager, nodeId);
+ serviceChangeListeners.put(nodeId, manager);
+ }
+
+ private void notifyServiceChangeListeners(final NodeId nodeId, final boolean success){
+ if (serviceChangeListeners.size() == 0) {
+ return;
+ }
+ LOG.debug("Notifying registered listeners for service change, no. of listeners {}", serviceChangeListeners.size());
+ for (final Map.Entry<NodeId, ServiceChangeListener> nodeIdServiceChangeListenerEntry : serviceChangeListeners.entrySet()) {
+ if (nodeIdServiceChangeListenerEntry.getKey().equals(nodeId)) {
+ LOG.debug("Listener {} for service change for node {} was notified. Success was set on {}", nodeIdServiceChangeListenerEntry.getValue(), nodeId, success);
+ nodeIdServiceChangeListenerEntry.getValue().servicesChangeDone(nodeId, success);
+ serviceChangeListeners.remove(nodeId);
+ }
+ }
+ }
+
+ @Override
+ public void roleInitializationDone(final NodeId nodeId, final boolean success) {
+ if (!success) {
+ LOG.warn("Initialization phase for node {} in role context was NOT successful, closing connection.", nodeId);
+ closeConnection(nodeId);
+ } else {
+ LOG.info("initialization phase for node {} in role context was successful, continuing to next context.", nodeId);
+ }
+ }
+
+ public void closeConnection(final NodeId nodeId) {
+ LOG.debug("Close connection called for node {}", nodeId);
+ final DeviceContext deviceContext = getDeviceContext(nodeId);
+ if (null != deviceContext) {
+ deviceContext.shutdownConnection();
+ }
+ }
+
+ @Override
+ public void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
+
+ final DeviceContext deviceContext = getDeviceContext(nodeId);
+
+ if (null == deviceContext) {
+ LOG.warn("Something went wrong, device context for nodeId: {} doesn't exists");
+ return;
+ }
+ if (!success) {
+ LOG.warn("Role change to {} in role context for node {} was NOT successful, closing connection", newRole, nodeId);
+ closeConnection(nodeId);
+ } else {
+ if (initializationPhase) {
+ LOG.debug("Initialization phase skipping starting services.");
+ return;
+ }
+ LOG.info("Role change to {} in role context for node {} was successful, staring/stopping services.", newRole, nodeId);
+
+ //TODO: This is old way to check if statistics is running, remove after statistics changes implemented
+ final DeviceState deviceState = deviceContext.getDeviceState();
+ if (null != deviceState) {
+ if (OfpRole.BECOMEMASTER.equals(newRole) && (getDeviceContext(nodeId) != null)) {
+ deviceState.setRole(OfpRole.BECOMEMASTER);
+ } else {
+ deviceState.setRole(OfpRole.BECOMESLAVE);
+ }
+ }
+
+ final ListenableFuture<Void> onClusterRoleChange = deviceContext.onClusterRoleChange(null, newRole);
+ Futures.addCallback(onClusterRoleChange, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(@Nullable final Void aVoid) {
+ LOG.info("Starting/Stopping services for node {} was successful", nodeId);
+ if (newRole.equals(OfpRole.BECOMESLAVE)) notifyServiceChangeListeners(nodeId, true);
+ }
+
+ @Override
+ public void onFailure(final Throwable throwable) {
+ LOG.warn("Starting/Stopping services for node {} was NOT successful, closing connection", nodeId);
+ closeConnection(nodeId);
+ }
+ });
+ }
+ }
+
+ public MessageIntelligenceAgency getMessageIntelligenceAgency() {
+ return messageIntelligenceAgency;
+ }
+
+ @Override
+ public DeviceContext getDeviceContext(final NodeId nodeId){
+ return deviceManager.getDeviceContextFromNodeId(nodeId);
+ }
+
+ public Short gainVersionSafely(final NodeId nodeId) {
+ return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getFeatures().getVersion() : null;
+ }
+
+ public Timeout newTimeout(@Nonnull TimerTask task, long delay, @Nonnull TimeUnit unit) {
+ return hashedWheelTimer.newTimeout(task, delay, unit);
+ }
+
+ public ConnectionContext.CONNECTION_STATE gainConnectionStateSafely(final NodeId nodeId){
+ return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getConnectionState() : null;
+ }
+
+ public Long reserveXidForDeviceMessage(final NodeId nodeId){
+ return null != getDeviceContext(nodeId) ? getDeviceContext(nodeId).reserveXidForDeviceMessage() : null;
+ }
+
+ @Override
+ public void deviceStartInitializationDone(final NodeId nodeId, final boolean success) {
+ if (!success) {
+ LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
+ closeConnection(nodeId);
+ } else {
+ LOG.info("initialization phase for node {} in device context was successful. Continuing to next context.", nodeId);
+ }
+ }
+
+ @Override
+ public void deviceInitializationDone(final NodeId nodeId, final boolean success) {
+ if (!success) {
+ LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
+ closeConnection(nodeId);
+ } else {
+ LOG.info("initialization phase for node {} in device context was successful. All phases initialized OK.", nodeId);
+ }
+ }
+}
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import javax.annotation.Nonnull;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * Created by Martin Bobak <mbobak@cisco.com> on 27.3.2015.
- */
public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginExtensionRegistratorProvider {
private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderImpl.class);
private boolean isStatisticsPollingOff = false;
private boolean isStatisticsRpcEnabled;
+ private final LifecycleConductor conductor;
+
public OpenFlowPluginProviderImpl(final long rpcRequestsQuota, final Long globalNotificationQuota) {
Preconditions.checkArgument(rpcRequestsQuota > 0 && rpcRequestsQuota <= Integer.MAX_VALUE, "rpcRequestQuota has to be in range <1,%s>", Integer.MAX_VALUE);
this.rpcRequestsQuota = (int) rpcRequestsQuota;
this.globalNotificationQuota = Preconditions.checkNotNull(globalNotificationQuota);
+ conductor = new LifecycleConductorImpl(messageIntelligenceAgency);
}
@Override
}
@Override
- public void onFailure(final Throwable t) {
+ public void onFailure(@Nonnull final Throwable t) {
LOG.warn("Some switchConnectionProviders failed to start.", t);
}
});
registerMXBean(messageIntelligenceAgency);
- deviceManager = new DeviceManagerImpl(dataBroker, messageIntelligenceAgency, globalNotificationQuota,
- switchFeaturesMandatory, barrierInterval, barrierCountLimit);
+ deviceManager = new DeviceManagerImpl(dataBroker,
+ globalNotificationQuota,
+ switchFeaturesMandatory,
+ barrierInterval,
+ barrierCountLimit,
+ conductor);
((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
- roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker);
- statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOff);
- rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota);
+
+ conductor.setSafelyDeviceManager(deviceManager);
+
+ roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker, conductor);
+ statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOff, conductor);
+ rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota, conductor);
+
+ roleManager.addRoleChangeListener((RoleChangeListener) conductor);
/* Initialization Phase ordering - OFP Device Context suite */
// CM -> DM -> SM -> RPC -> Role -> DM
statisticsManager.setDeviceTerminationPhaseHandler(roleManager);
roleManager.setDeviceTerminationPhaseHandler(deviceManager);
- rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
- rpcManager.setNotificationPublishService(notificationPublishService);
-
- deviceManager.setNotificationService(this.notificationProviderService);
- deviceManager.setNotificationPublishService(this.notificationPublishService);
+ deviceManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
+ deviceManager.setNotificationPublishService(notificationPublishService);
TranslatorLibraryUtil.setBasicTranslatorLibrary(deviceManager);
deviceManager.initialize();
import java.math.BigInteger;
import java.net.InetSocketAddress;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
}
@Override
- public void closeConnection(boolean propagate) {
+ public void closeConnection(final boolean propagate) {
if (null == nodeId){
SessionStatistics.countEvent(connectionAdapter.getRemoteAddress().toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
} else {
connectionAdapter.getRemoteAddress(), datapathId);
connectionState = ConnectionContext.CONNECTION_STATE.RIP;
- unregisterOutboundQueue();
+ Future<Void> future = Executors.newSingleThreadExecutor().submit(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ unregisterOutboundQueue();
+ return null;
+ }
+ });
+ try {
+ LOG.debug("Waiting 1s for unregistering outbound queue.");
+ future.get(1, TimeUnit.SECONDS);
+ LOG.info("Unregistering outbound queue successful.");
+ } catch (InterruptedException e) {
+ LOG.warn("Unregistering outbound queue was interrupted for node {}", nodeId);
+ } catch (ExecutionException e) {
+ LOG.warn("Unregistering outbound queue throws exception for node {}", nodeId, e);
+ } catch (TimeoutException e) {
+ LOG.warn("Unregistering outbound queue took longer than 1 seconds for node {}", nodeId);
+ }
+
closeHandshakeContext();
if (getConnectionAdapter().isAlive()) {
}
if (propagate) {
+ LOG.debug("Propagating device disconnect for node {}", nodeId);
propagateDeviceDisconnectedEvent();
+ } else {
+ LOG.debug("Close connection without propagating for node {}", nodeId);
}
}
private void closeHandshakeContext() {
+ LOG.debug("Trying closing handshake context for node {}", nodeId);
if (handshakeContext != null) {
try {
handshakeContext.close();
}
private void unregisterOutboundQueue() {
+ LOG.debug("Trying unregister outbound queue handler registration for node {}", nodeId);
if (outboundQueueHandlerRegistration != null) {
outboundQueueHandlerRegistration.close();
outboundQueueHandlerRegistration = null;
public void onSuccess(@Nullable final RpcResult<BarrierOutput> result) {
LOG.debug("succeeded by getting sweep barrier after posthandshake for device {}", connectionContext.getNodeId());
try {
- deviceConnectedHandler.deviceConnected(connectionContext);
+ if (!deviceConnectedHandler.deviceConnected(connectionContext)) {
+ connectionContext.closeConnection(true);
+ }
SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
} catch (final Exception e) {
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
-import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import java.math.BigInteger;
-import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
-import org.opendaylight.controller.md.sal.binding.api.NotificationService;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.openflowplugin.impl.registry.group.DeviceGroupRegistryImpl;
import org.opendaylight.openflowplugin.impl.registry.meter.DeviceMeterRegistryImpl;
+import org.opendaylight.openflowplugin.impl.rpc.RpcContextImpl;
import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtils;
import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
private static final Logger LOG = LoggerFactory.getLogger(DeviceContextImpl.class);
// TODO: drain factor should be parametrized
- public static final float REJECTED_DRAIN_FACTOR = 0.25f;
+ private static final float REJECTED_DRAIN_FACTOR = 0.25f;
// TODO: low water mark factor should be parametrized
private static final float LOW_WATERMARK_FACTOR = 0.75f;
// TODO: high water mark factor should be parametrized
private final ConnectionContext primaryConnectionContext;
private final DeviceState deviceState;
private final DataBroker dataBroker;
- private final HashedWheelTimer hashedWheelTimer;
private final Map<SwitchConnectionDistinguisher, ConnectionContext> auxiliaryConnectionContexts;
private final TransactionChainManager transactionChainManager;
private final DeviceFlowRegistry deviceFlowRegistry;
private final DeviceGroupRegistry deviceGroupRegistry;
private final DeviceMeterRegistry deviceMeterRegistry;
- private final Collection<DeviceTerminationPhaseHandler> closeHandlers = new HashSet<>();
private final PacketInRateLimiter packetInLimiter;
private final MessageSpy messageSpy;
private final ItemLifeCycleKeeper flowLifeCycleKeeper;
private NotificationPublishService notificationPublishService;
- private NotificationService notificationService;
private final OutboundQueue outboundQueueProvider;
private Timeout barrierTaskTimeout;
private final MessageTranslator<PortGrouping, FlowCapableNodeConnector> portStatusTranslator;
private final boolean switchFeaturesMandatory;
private StatisticsContext statisticsContext;
+ private final NodeId nodeId;
+
private volatile DEVICE_CONTEXT_STATE deviceCtxState;
+ private boolean isStatisticsRpcEnabled;
@VisibleForTesting
DeviceContextImpl(@Nonnull final ConnectionContext primaryConnectionContext,
@Nonnull final DeviceState deviceState,
@Nonnull final DataBroker dataBroker,
- @Nonnull final HashedWheelTimer hashedWheelTimer,
@Nonnull final MessageSpy _messageSpy,
@Nonnull final OutboundQueueProvider outboundQueueProvider,
@Nonnull final TranslatorLibrary translatorLibrary,
this.primaryConnectionContext = Preconditions.checkNotNull(primaryConnectionContext);
this.deviceState = Preconditions.checkNotNull(deviceState);
this.dataBroker = Preconditions.checkNotNull(dataBroker);
- this.hashedWheelTimer = Preconditions.checkNotNull(hashedWheelTimer);
this.outboundQueueProvider = Preconditions.checkNotNull(outboundQueueProvider);
this.transactionChainManager = new TransactionChainManager(dataBroker, deviceState);
auxiliaryConnectionContexts = new HashMap<>();
flowLifeCycleKeeper = new ItemLifeCycleSourceImpl();
itemLifeCycleSourceRegistry.registerLifeCycleSource(flowLifeCycleKeeper);
deviceCtxState = DEVICE_CONTEXT_STATE.INITIALIZATION;
+
+ nodeId = primaryConnectionContext.getNodeId();
}
/**
}
@Override
- public Long reservedXidForDeviceMessage() {
+ public Long reserveXidForDeviceMessage() {
return outboundQueueProvider.reserveEntry();
}
@Override
public void removeAuxiliaryConnectionContext(final ConnectionContext connectionContext) {
final SwitchConnectionDistinguisher connectionDistinguisher = createConnectionDistinguisher(connectionContext);
- if (null != connectionDistinguisher) {
- LOG.debug("auxiliary connection dropped: {}, nodeId:{}", connectionContext.getConnectionAdapter()
- .getRemoteAddress(), getDeviceState().getNodeId());
- auxiliaryConnectionContexts.remove(connectionDistinguisher);
- }
+ LOG.debug("auxiliary connection dropped: {}, nodeId:{}", connectionContext.getConnectionAdapter()
+ .getRemoteAddress(), nodeId);
+ auxiliaryConnectionContexts.remove(connectionDistinguisher);
}
@Override
@Override
public ListenableFuture<Void> onClusterRoleChange(final OfpRole oldRole, @CheckForNull final OfpRole role) {
- LOG.trace("onClusterRoleChange {} for node:", role, deviceState.getNodeId());
+ LOG.trace("onClusterRoleChange {} for node:", role, nodeId);
Preconditions.checkArgument(role != null);
if (role.equals(oldRole)) {
- LOG.debug("Demanded role change for device {} is not changed. OldRole: {}, NewRole {}", deviceState.getNodeId(), oldRole, role);
+ LOG.debug("Demanded role change for device {} is not changed. OldRole: {}, NewRole {}", nodeId, oldRole, role);
return Futures.immediateFuture(null);
}
if (OfpRole.BECOMEMASTER.equals(role)) {
} else if (OfpRole.BECOMESLAVE.equals(role)) {
return onDeviceLostClusterLeadership();
} else {
- LOG.warn("Unknown OFCluster Role {} for Node {}", role, deviceState.getNodeId());
+ LOG.warn("Unknown OFCluster Role {} for Node {}", role, nodeId);
if (null != rpcContext) {
MdSalRegistrationUtils.unregisterServices(rpcContext);
}
@Override
public ListenableFuture<Void> onDeviceLostClusterLeadership() {
- LOG.trace("onDeviceLostClusterLeadership for node: {}", deviceState.getNodeId());
+ LOG.trace("onDeviceLostClusterLeadership for node: {}", nodeId);
if (null != rpcContext) {
MdSalRegistrationUtils.registerSlaveServices(rpcContext, OfpRole.BECOMESLAVE);
}
@Override
public ListenableFuture<Void> onDeviceTakeClusterLeadership() {
- LOG.trace("onDeviceTakeClusterLeadership for node: {}", deviceState.getNodeId());
+ LOG.trace("onDeviceTakeClusterLeadership for node: {}", nodeId);
/* validation */
if (statisticsContext == null) {
- final String errMsg = String.format("DeviceCtx %s is up but we are missing StatisticsContext", deviceState.getNodeId());
+ final String errMsg = String.format("DeviceCtx %s is up but we are missing StatisticsContext", nodeId);
LOG.warn(errMsg);
return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
}
if (rpcContext == null) {
- final String errMsg = String.format("DeviceCtx %s is up but we are missing RpcContext", deviceState.getNodeId());
+ final String errMsg = String.format("DeviceCtx %s is up but we are missing RpcContext", nodeId);
LOG.warn(errMsg);
return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
}
/* Routed RPC registration */
MdSalRegistrationUtils.registerMasterServices(getRpcContext(), DeviceContextImpl.this, OfpRole.BECOMEMASTER);
- getRpcContext().registerStatCompatibilityServices();
+
+ if (isStatisticsRpcEnabled) {
+ MdSalRegistrationUtils.registerStatCompatibilityServices(getRpcContext(), this,
+ notificationPublishService, new AtomicLong());
+ }
/* Prepare init info collecting */
getDeviceState().setDeviceSynchronized(false);
new AsyncFunction<Void, Boolean>() {
@Override
- public ListenableFuture<Boolean> apply(final Void input) throws Exception {
+ public ListenableFuture<Boolean> apply(@Nonnull final Void input) throws Exception {
getStatisticsContext().statListForCollectingInitialization();
return getStatisticsContext().gatherDynamicData();
}
LOG.warn(errMsg);
throw new IllegalStateException(errMsg);
}
- if (!input.booleanValue()) {
+ if (!input) {
final String errMsg = String.format("Get Initial Device %s information fails",
getDeviceState().getNodeId());
LOG.warn(errMsg);
throw new IllegalStateException(errMsg);
}
- LOG.debug("Get Initial Device {} information is successful", getDeviceState().getNodeId());
+ LOG.debug("Get Initial Device {} information is successful", nodeId);
getDeviceState().setDeviceSynchronized(true);
initialSubmitTransaction();
getDeviceState().setStatisticsPollingEnabledProp(true);
@Override
public <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
- final InstanceIdentifier<T> path, final T data) {
+ final InstanceIdentifier<T> path, final T data) throws Exception {
transactionChainManager.writeToTransaction(store, path, data);
}
@Override
- public <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
+ public <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path) throws Exception {
transactionChainManager.addDeleteOperationTotTxChain(store, path);
}
final FlowCapableNodeConnector flowCapableNodeConnector = portStatusTranslator.translate(portStatus, this, null);
final KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> iiToNodeConnector = provideIIToNodeConnector(portStatus.getPortNo(), portStatus.getVersion());
- if (portStatus.getReason().equals(PortReason.OFPPRADD) || portStatus.getReason().equals(PortReason.OFPPRMODIFY)) {
- // because of ADD status node connector has to be created
- final NodeConnectorBuilder nConnectorBuilder = new NodeConnectorBuilder().setKey(iiToNodeConnector.getKey());
- nConnectorBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, new FlowCapableNodeConnectorStatisticsDataBuilder().build());
- nConnectorBuilder.addAugmentation(FlowCapableNodeConnector.class, flowCapableNodeConnector);
- writeToTransaction(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector, nConnectorBuilder.build());
- } else if (portStatus.getReason().equals(PortReason.OFPPRDELETE)) {
- addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector);
+ try {
+ if (portStatus.getReason().equals(PortReason.OFPPRADD) || portStatus.getReason().equals(PortReason.OFPPRMODIFY)) {
+ // because of ADD status node connector has to be created
+ final NodeConnectorBuilder nConnectorBuilder = new NodeConnectorBuilder().setKey(iiToNodeConnector.getKey());
+ nConnectorBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, new FlowCapableNodeConnectorStatisticsDataBuilder().build());
+ nConnectorBuilder.addAugmentation(FlowCapableNodeConnector.class, flowCapableNodeConnector);
+ writeToTransaction(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector, nConnectorBuilder.build());
+ } else if (portStatus.getReason().equals(PortReason.OFPPRDELETE)) {
+ addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector);
+ }
+ submitTransaction();
+ } catch (final Exception e) {
+ LOG.warn("Error processing port status message: {}", e.getMessage());
}
- submitTransaction();
}
private KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> provideIIToNodeConnector(final long portNo, final short version) {
return;
}
- final ListenableFuture<? extends Object> offerNotification = notificationPublishService.offerNotification(packetReceived);
+ final ListenableFuture<?> offerNotification = notificationPublishService.offerNotification(packetReceived);
if (NotificationPublishService.REJECTED.equals(offerNotification)) {
LOG.debug("notification offer rejected");
messageSpy.spyMessage(packetReceived.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_NOTIFICATION_REJECTED);
return translatorLibrary;
}
- @Override
- public HashedWheelTimer getTimer() {
- return hashedWheelTimer;
- }
-
@Override
public synchronized void close() {
LOG.debug("closing deviceContext: {}, nodeId:{}",
return barrierTaskTimeout;
}
- @Override
- public void setNotificationService(final NotificationService notificationService) {
- this.notificationService = notificationService;
- }
-
@Override
public void setNotificationPublishService(final NotificationPublishService notificationPublishService) {
this.notificationPublishService = notificationPublishService;
return messageSpy;
}
- @Override
- public void addDeviceContextClosedHandler(final DeviceTerminationPhaseHandler deviceContextClosedHandler) {
- closeHandlers.add(deviceContextClosedHandler);
- }
-
@Override
public void onPublished() {
Verify.verify(DEVICE_CONTEXT_STATE.INITIALIZATION.equals(deviceCtxState));
}
@Override
- public void storeNodeConnectorRef(final Long portNumber, final NodeConnectorRef nodeConnectorRef) {
+ public void storeNodeConnectorRef(@Nonnull final Long portNumber, @Nonnull final NodeConnectorRef nodeConnectorRef) {
nodeConnectorCache.put(
Preconditions.checkNotNull(portNumber),
Preconditions.checkNotNull(nodeConnectorRef));
@Override
public synchronized void shutdownConnection() {
- LOG.trace("shutdown method for node {}", deviceState.getNodeId());
+ LOG.debug("Shutdown method for node {}", nodeId);
deviceState.setValid(false);
if (DEVICE_CONTEXT_STATE.TERMINATION.equals(deviceCtxState)) {
- LOG.debug("DeviceCtx for Node {} is in termination process.", deviceState.getNodeId());
+ LOG.debug("DeviceCtx for Node {} is in termination process.", nodeId);
return;
}
deviceCtxState = DEVICE_CONTEXT_STATE.TERMINATION;
- for (final Iterator<ConnectionContext> iterator = Iterators.consumingIterator(auxiliaryConnectionContexts
- .values().iterator()); iterator.hasNext();) {
- iterator.next().closeConnection(false);
- }
+
if (ConnectionContext.CONNECTION_STATE.RIP.equals(getPrimaryConnectionContext().getConnectionState())) {
LOG.debug("ConnectionCtx for Node {} is in RIP state.", deviceState.getNodeId());
return;
}
/* Terminate Auxiliary Connection */
for (final ConnectionContext connectionContext : auxiliaryConnectionContexts.values()) {
+ LOG.debug("Closing auxiliary connection {}", connectionContext.getNodeId());
connectionContext.closeConnection(false);
}
/* Terminate Primary Connection */
deviceMeterRegistry.close();
}
+ @Override
+ public void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled) {
+ this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
+ }
+
@Override
public DEVICE_CONTEXT_STATE getDeviceContextState() {
return deviceCtxState;
*/
package org.opendaylight.openflowplugin.impl.device;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import java.util.Collections;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
import org.opendaylight.openflowplugin.impl.connection.OutboundQueueProviderImpl;
private static final Logger LOG = LoggerFactory.getLogger(DeviceManagerImpl.class);
- private static final long TICK_DURATION = 10; // 0.5 sec.
private final long globalNotificationQuota;
private final boolean switchFeaturesMandatory;
- private ScheduledThreadPoolExecutor spyPool;
private final int spyRate = 10;
private final DataBroker dataBroker;
- private final HashedWheelTimer hashedWheelTimer;
private TranslatorLibrary translatorLibrary;
private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
- private NotificationService notificationService;
private NotificationPublishService notificationPublishService;
private final ConcurrentMap<NodeId, DeviceContext> deviceContexts = new ConcurrentHashMap<>();
- private final MessageIntelligenceAgency messageIntelligenceAgency;
private final long barrierIntervalNanos;
private final int barrierCountLimit;
private ExtensionConverterProvider extensionConverterProvider;
+ private ScheduledThreadPoolExecutor spyPool;
+
+ private final LifecycleConductor conductor;
+ private boolean isStatisticsRpcEnabled;
public DeviceManagerImpl(@Nonnull final DataBroker dataBroker,
- @Nonnull final MessageIntelligenceAgency messageIntelligenceAgency,
final long globalNotificationQuota, final boolean switchFeaturesMandatory,
- final long barrierInterval, final int barrierCountLimit) {
+ final long barrierInterval, final int barrierCountLimit,
+ final LifecycleConductor lifecycleConductor) {
this.switchFeaturesMandatory = switchFeaturesMandatory;
this.globalNotificationQuota = globalNotificationQuota;
this.dataBroker = Preconditions.checkNotNull(dataBroker);
- hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, 500);
/* merge empty nodes to oper DS to predict any problems with missing parent for Node */
final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
throw new IllegalStateException(e);
}
- this.messageIntelligenceAgency = messageIntelligenceAgency;
this.barrierIntervalNanos = TimeUnit.MILLISECONDS.toNanos(barrierInterval);
this.barrierCountLimit = barrierCountLimit;
+
+ this.conductor = lifecycleConductor;
+ spyPool = new ScheduledThreadPoolExecutor(1);
}
}
@Override
- public void onDeviceContextLevelUp(final DeviceContext deviceContext) throws Exception {
+ public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
// final phase - we have to add new Device to MD-SAL DataStore
- LOG.debug("Final phase of DeviceContextLevelUp for Node: {} ", deviceContext.getDeviceState().getNodeId());
- Preconditions.checkNotNull(deviceContext);
+ LOG.debug("Final phase of DeviceContextLevelUp for Node: {} ", nodeId);
+ DeviceContext deviceContext = Preconditions.checkNotNull(deviceContexts.get(nodeId));
((DeviceContextImpl) deviceContext).initialSubmitTransaction();
deviceContext.onPublished();
}
@Override
- public void deviceConnected(@CheckForNull final ConnectionContext connectionContext) throws Exception {
+ public boolean deviceConnected(@CheckForNull final ConnectionContext connectionContext) throws Exception {
Preconditions.checkArgument(connectionContext != null);
- Preconditions.checkState(!deviceContexts.containsKey(connectionContext.getNodeId()),
- "Rejecting connection from node which is already connected and there exist deviceContext for it: {}",
- connectionContext.getNodeId()
- );
+
+ NodeId nodeId = connectionContext.getNodeId();
+ /**
+ * This part prevent destroy another device context. Throwing here an exception result to propagate close connection
+ * in {@link org.opendaylight.openflowplugin.impl.connection.org.opendaylight.openflowplugin.impl.connection.HandshakeContextImpl}
+ * If context already exist we are in state closing process (connection flapping) and we should not propagate connection close
+ */
+ if (deviceContexts.containsKey(nodeId)) {
+ LOG.warn("Rejecting connection from node which is already connected and there exist deviceContext for it: {}", connectionContext.getNodeId());
+ return false;
+ }
+
LOG.info("ConnectionEvent: Device connected to controller, Device:{}, NodeId:{}",
- connectionContext.getConnectionAdapter().getRemoteAddress(), connectionContext.getNodeId());
+ connectionContext.getConnectionAdapter().getRemoteAddress(), nodeId);
// Add Disconnect handler
connectionContext.setDeviceDisconnectedHandler(DeviceManagerImpl.this);
connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
final DeviceState deviceState = createDeviceState(connectionContext);
- final DeviceContext deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker,
- hashedWheelTimer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, switchFeaturesMandatory);
+ final DeviceContext deviceContext = new DeviceContextImpl(connectionContext,
+ deviceState,
+ dataBroker,
+ conductor.getMessageIntelligenceAgency(),
+ outboundQueueProvider,
+ translatorLibrary,
+ switchFeaturesMandatory);
- Verify.verify(deviceContexts.putIfAbsent(connectionContext.getNodeId(), deviceContext) == null, "DeviceCtx still not closed.");
- deviceContext.addDeviceContextClosedHandler(this);
+ Verify.verify(deviceContexts.putIfAbsent(nodeId, deviceContext) == null, "DeviceCtx still not closed.");
((ExtensionConverterProviderKeeper) deviceContext).setExtensionConverterProvider(extensionConverterProvider);
- deviceContext.setNotificationService(notificationService);
+ deviceContext.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
deviceContext.setNotificationPublishService(notificationPublishService);
updatePacketInRateLimiters();
connectionAdapter.setMessageListener(messageListener);
deviceState.setValid(true);
- deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
+ deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
+
+ return true;
}
private static DeviceStateImpl createDeviceState(final @Nonnull ConnectionContext connectionContext) {
this.translatorLibrary = translatorLibrary;
}
- @Override
- public void setNotificationService(final NotificationService notificationServiceParam) {
- notificationService = notificationServiceParam;
- }
-
@Override
public void setNotificationPublishService(final NotificationPublishService notificationService) {
notificationPublishService = notificationService;
@Override
public void initialize() {
- spyPool = new ScheduledThreadPoolExecutor(1);
- spyPool.scheduleAtFixedRate(messageIntelligenceAgency, spyRate, spyRate, TimeUnit.SECONDS);
+ spyPool.scheduleAtFixedRate(conductor.getMessageIntelligenceAgency(), spyRate, spyRate, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public DeviceContext getDeviceContextFromNodeId(final NodeId nodeId) {
+ return deviceContexts.get(nodeId);
+ }
+
+ @Override
+ public void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled) {
+ this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
}
@Override
@Override
public void onDeviceDisconnected(final ConnectionContext connectionContext) {
LOG.trace("onDeviceDisconnected method call for Node: {}", connectionContext.getNodeId());
- Preconditions.checkArgument(connectionContext != null);
final NodeId nodeId = connectionContext.getNodeId();
final DeviceContext deviceCtx = this.deviceContexts.get(nodeId);
if (null == deviceCtx) {
- LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.",
- connectionContext.getNodeId());
+ LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.", nodeId);
return;
}
@Override
public void onSuccess(final Void result) {
- LOG.debug("TxChainManager for device {} is closed successful.", deviceCtx.getDeviceState().getNodeId());
+ LOG.debug("TxChainManager for device {} is closed successful.", nodeId);
deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceCtx);
}
@Override
public void onFailure(final Throwable t) {
- LOG.warn("TxChainManager for device {} failed by closing.", deviceCtx.getDeviceState().getNodeId(), t);
+ LOG.warn("TxChainManager for device {} failed by closing.", nodeId, t);
deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceCtx);
}
});
@Override
public void run(final Timeout timeout) throws Exception {
if (!future.isDone()) {
- LOG.info("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.",
- deviceCtx.getDeviceState().getNodeId());
+ LOG.info("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", nodeId);
future.cancel(false);
}
}
};
- deviceCtx.getTimer().newTimeout(timerTask, 10, TimeUnit.SECONDS);
+ conductor.newTimeout(timerTask, 10, TimeUnit.SECONDS);
}
}
+
+ @VisibleForTesting
+ void addDeviceContextToMap(final NodeId nodeId, final DeviceContext deviceContext){
+ deviceContexts.put(nodeId, deviceContext);
+ }
}
}
<T extends DataObject> void addDeleteOperationTotTxChain(final LogicalDatastoreType store,
- final InstanceIdentifier<T> path) {
+ final InstanceIdentifier<T> path) throws Exception {
final WriteTransaction writeTx = getTransactionSafely();
if (writeTx != null) {
+ LOG.trace("addDeleteOperation called with path {} ", path);
writeTx.delete(store, path);
} else {
LOG.debug("WriteTx is null for node {}. Delete {} was not realized.", nodeII, path);
+ throw new Exception("Cannot write into transaction.");
}
}
<T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
- final InstanceIdentifier<T> path, final T data) {
+ final InstanceIdentifier<T> path, final T data) throws Exception {
final WriteTransaction writeTx = getTransactionSafely();
if (writeTx != null) {
+ LOG.trace("writeToTransaction called with path {} ", path);
writeTx.put(store, path, data);
} else {
LOG.debug("WriteTx is null for node {}. Write data for {} was not realized.", nodeII, path);
+ throw new Exception("Cannot write into transaction.");
}
}
}
ListenableFuture<Void> shuttingDown() {
- LOG.debug("TxManager is going SUTTING_DOWN for node {}", nodeII);
+ LOG.debug("TxManager is going SHUTTING_DOWN for node {}", nodeII);
ListenableFuture<Void> future;
synchronized (txLock) {
this.transactionChainManagerStatus = TransactionChainManagerStatus.SHUTTING_DOWN;
*/
package org.opendaylight.openflowplugin.impl.role;
-import javax.annotation.Nullable;
-import java.util.concurrent.Future;
-
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.Timeout;
-import io.netty.util.TimerTask;
-import java.util.concurrent.Future;
+
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
+import org.opendaylight.openflowplugin.impl.LifecycleConductorImpl;
import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
-import org.opendaylight.openflowplugin.impl.services.SalRoleServiceImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Created by kramesha on 9/12/15.
+ * Role context hold information about entity ownership registration,
+ * register and unregister candidate (main and tx)
*/
-public class RoleContextImpl implements RoleContext {
+class RoleContextImpl implements RoleContext {
+
private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
+ private static final int TIMEOUT = 12;
+ private final NodeId nodeId;
private final EntityOwnershipService entityOwnershipService;
- private EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
- private EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration;
-
- private final DeviceContext deviceContext;
+ private volatile EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration = null;
+ private volatile EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration = null;
- @GuardedBy("mainCandidateGuard")
private final Entity entity;
- @GuardedBy("txCandidateGuard")
private final Entity txEntity;
- private SalRoleService salRoleService;
+ private SalRoleService salRoleService = null;
private final Semaphore roleChangeGuard = new Semaphore(1, true);
- @GuardedBy("roleChangeGuard")
- private OfpRole clusterRole;
+ private final LifecycleConductor conductor;
- public RoleContextImpl(final DeviceContext deviceContext, final EntityOwnershipService entityOwnershipService,
- final Entity entity, final Entity txEntity) {
- this.entityOwnershipService = Preconditions.checkNotNull(entityOwnershipService);
- this.deviceContext = Preconditions.checkNotNull(deviceContext);
- this.entity = Preconditions.checkNotNull(entity);
- this.txEntity = Preconditions.checkNotNull(txEntity);
- salRoleService = new SalRoleServiceImpl(this, deviceContext);
- clusterRole = OfpRole.BECOMESLAVE;
+ public RoleContextImpl(final NodeId nodeId, final EntityOwnershipService entityOwnershipService, final Entity entity, final Entity txEntity, final LifecycleConductor lifecycleConductor) {
+ this.entityOwnershipService = entityOwnershipService;
+ this.entity = entity;
+ this.txEntity = txEntity;
+ this.nodeId = nodeId;
+ this.conductor = lifecycleConductor;
}
@Override
- public void initializationRoleContext() {
- LOG.trace("Initialization MainCandidate for Node {}", deviceContext.getDeviceState().getNodeId());
- final AsyncFunction<RpcResult<SetRoleOutput>, Void> initFunction = new AsyncFunction<RpcResult<SetRoleOutput>, Void>() {
- @Override
- public ListenableFuture<Void> apply(final RpcResult<SetRoleOutput> input) throws Exception {
- LOG.debug("Initialization request OpenflowEntityOwnership for entity {}", entity);
- getDeviceState().setRole(OfpRole.BECOMESLAVE);
- entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity);
- LOG.debug("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext
- .getPrimaryConnectionContext().getNodeId().getValue());
- return Futures.immediateFuture(null);
- }
- };
-
- try {
- roleChangeGuard.acquire();
- final ListenableFuture<Void> roleChange = sendRoleChangeToDevice(OfpRole.BECOMESLAVE, initFunction);
- Futures.addCallback(roleChange, new FutureCallback<Void>() {
-
- @Override
- public void onSuccess(final Void result) {
- LOG.debug("Initial RoleContext for Node {} is successful", deviceContext.getDeviceState().getNodeId());
- roleChangeGuard.release();
- }
-
- @Override
- public void onFailure(final Throwable t) {
- LOG.warn("Initial RoleContext for Node {} fail", deviceContext.getDeviceState().getNodeId(), t);
- roleChangeGuard.release();
- deviceContext.shutdownConnection();
- }
- });
- } catch (final Exception e) {
- LOG.warn("Unexpected exception bu Initialization RoleContext for Node {}", deviceContext.getDeviceState().getNodeId(), e);
- roleChangeGuard.release();
- deviceContext.shutdownConnection();
- }
- }
-
- @Override
- public void terminationRoleContext() {
- LOG.trace("Termination MainCandidate for Node {}", deviceContext.getDeviceState().getNodeId());
- if (null != entityOwnershipCandidateRegistration) {
- LOG.debug("Closing EntityOwnershipCandidateRegistration for {}", entity);
- try {
- roleChangeGuard.acquire();
- } catch (final InterruptedException e) {
- LOG.warn("Unexpected exception in closing EntityOwnershipCandidateRegistration process for entity {}", entity);
- } finally {
- entityOwnershipCandidateRegistration.close();
- entityOwnershipCandidateRegistration = null;
- // FIXME: call suspendTxCandidate here means lost protection for possible Delete Node before take ownership
- // by another ClusterNode, but it stabilized cluster behavior in general - So try to find another solution
- suspendTxCandidate();
- roleChangeGuard.release();
- }
- }
- }
-
- @Override
- public void onDeviceTryToTakeClusterLeadership() {
- LOG.trace("onDeviceTryToTakeClusterLeadership method call for Entity {}", entity);
- boolean callShutdown = false;
- try {
- roleChangeGuard.acquire();
- Verify.verify(null != entityOwnershipCandidateRegistration);
- Verify.verify(OfpRole.BECOMESLAVE.equals(clusterRole));
-
- clusterRole = OfpRole.BECOMEMASTER;
- /* register TxCandidate and wait for mainCandidateGuard release from onDeviceTakeLeadership method */
- setupTxCandidate();
-
- } catch (final Exception e) {
- LOG.warn("Unexpected exception in roleChange process for entity {}", entity);
- callShutdown = true;
- } finally {
- roleChangeGuard.release();
- }
- if (callShutdown) {
- deviceContext.shutdownConnection();
- }
+ public boolean initialization() {
+ LOG.info("Initialization main candidate for node {}", nodeId);
+ return registerCandidate(this.entity);
}
@Override
- public void onDeviceTakeClusterLeadership() {
- LOG.trace("onDeviceTakeClusterLeadership for entity {}", txEntity);
- try {
- roleChangeGuard.acquire();
- Verify.verify(null != txEntityOwnershipCandidateRegistration);
- Verify.verify(OfpRole.BECOMEMASTER.equals(clusterRole));
-
- if (null == entityOwnershipCandidateRegistration) {
- LOG.debug("EntityOwnership candidate for entity {} is closed.", txEntity);
- suspendTxCandidate();
- roleChangeGuard.release();
- return;
- }
-
- final ListenableFuture<Void> future = onRoleChanged(OfpRole.BECOMESLAVE, OfpRole.BECOMEMASTER);
- Futures.addCallback(future, new FutureCallback<Void>() {
-
- @Override
- public void onSuccess(final Void result) {
- LOG.debug("Take Leadership for node {} was successful", getDeviceState().getNodeId());
- roleChangeGuard.release();
- }
-
- @Override
- public void onFailure(final Throwable t) {
- LOG.warn("Take Leadership for node {} failed", getDeviceState().getNodeId(), t);
- roleChangeGuard.release();
- deviceContext.shutdownConnection();
- }
- });
-
- } catch (final Exception e) {
- LOG.warn("Unexpected exception in roleChange process for entity {}", txEntity);
- roleChangeGuard.release();
- deviceContext.shutdownConnection();
+ public void unregisterAllCandidates() {
+ LOG.info("Role context closed, unregistering all candidates for ownership for node {}", nodeId);
+ if (isMainCandidateRegistered()) {
+ unregisterCandidate(this.entity);
}
- };
-
- @Override
- public void onDeviceLostClusterLeadership() {
- LOG.trace("onDeviceLostClusterLeadership method call for Entity {}", entity);
- try {
- roleChangeGuard.acquire();
- Verify.verify(null != entityOwnershipCandidateRegistration);
- Verify.verify(null != txEntityOwnershipCandidateRegistration);
- Verify.verify(OfpRole.BECOMEMASTER.equals(clusterRole));
-
- clusterRole = OfpRole.BECOMESLAVE;
-
- final ListenableFuture<Void> future = onRoleChanged(OfpRole.BECOMEMASTER, OfpRole.BECOMESLAVE);
- Futures.addCallback(future, new FutureCallback<Void>() {
-
- @Override
- public void onSuccess(final Void result) {
- LOG.debug("Lost Leadership for node {} was successful", getDeviceState().getNodeId());
- suspendTxCandidate();
- roleChangeGuard.release();
- }
-
- @Override
- public void onFailure(final Throwable t) {
- LOG.debug("Lost Leadership for node {} faild", getDeviceState().getNodeId(), t);
- roleChangeGuard.release();
- deviceContext.shutdownConnection();
- }
-
- });
-
- } catch (final Exception e) {
- LOG.warn("Unexpected exception in roleChange process for entity {}", entity);
- roleChangeGuard.release();
- deviceContext.shutdownConnection();
+ if (isTxCandidateRegistered()) {
+ unregisterCandidate(this.txEntity);
}
}
+ @Nullable
@Override
- public boolean isMainCandidateRegistered() {
- final boolean result;
- try {
- roleChangeGuard.acquire();
- } catch (final InterruptedException e) {
- LOG.warn("Unexpected exception in check EntityOwnershipCandidateRegistration process for entity {}", entity);
- } finally {
- result = entityOwnershipCandidateRegistration != null;
- roleChangeGuard.release();
- }
- return result;
- }
-
- @Override
- public boolean isTxCandidateRegistered() {
- final boolean result;
- try {
- roleChangeGuard.acquire();
- } catch (final InterruptedException e) {
- LOG.warn("Unexpected exception in check TxEntityOwnershipCandidateRegistration process for txEntity {}", txEntity);
- } finally {
- result = txEntityOwnershipCandidateRegistration != null;
- roleChangeGuard.release();
- }
- return result;
- }
-
- @VisibleForTesting
- ListenableFuture<Void> onRoleChanged(final OfpRole oldRole, final OfpRole newRole) {
- LOG.trace("onRoleChanged method call for Entity {}", entity);
-
- if (!isDeviceConnected()) {
- // this can happen as after the disconnect, we still get a last message from EntityOwnershipService.
- LOG.debug("Device {} is disconnected from this node. Hence not attempting a role change.", deviceContext
- .getPrimaryConnectionContext().getNodeId());
- // we don't need to do anything
- return Futures.immediateFuture(null);
- }
-
- final AsyncFunction<RpcResult<SetRoleOutput>, Void> roleChangeFunction = new AsyncFunction<RpcResult<SetRoleOutput>, Void>() {
+ public <T> RequestContext<T> createRequestContext() {
+ return new AbstractRequestContext<T>(conductor.reserveXidForDeviceMessage(nodeId)) {
@Override
- public ListenableFuture<Void> apply(final RpcResult<SetRoleOutput> setRoleOutputRpcResult) throws Exception {
- LOG.debug("Role change {} successful made on switch :{}", newRole, deviceContext.getDeviceState().getNodeId());
- getDeviceState().setRole(newRole);
- return deviceContext.onClusterRoleChange(oldRole, newRole);
+ public void close() {
}
};
- return sendRoleChangeToDevice(newRole, roleChangeFunction);
}
- @GuardedBy("roleChangeGuard")
- private void setupTxCandidate() throws Exception {
- LOG.debug("setupTxCandidate for entity {} and Transaction entity {}", entity, txEntity);
- Verify.verify(txEntity != null);
- Verify.verify(entityOwnershipCandidateRegistration != null);
- Verify.verify(txEntityOwnershipCandidateRegistration == null);
- txEntityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(txEntity);
- }
-
- @GuardedBy("roleChangeGuard")
- private void suspendTxCandidate() {
- LOG.trace("Suspend TxCandidate for Node {}", deviceContext.getDeviceState().getNodeId());
- if (null != txEntityOwnershipCandidateRegistration) {
- LOG.debug("Closing TxEntityOwnershipCandidateRegistration for {}", txEntity);
- txEntityOwnershipCandidateRegistration.close();
- txEntityOwnershipCandidateRegistration = null;
- }
+ @Override
+ public void setSalRoleService(@Nonnull final SalRoleService salRoleService) {
+ Preconditions.checkNotNull(salRoleService);
+ this.salRoleService = salRoleService;
}
@Override
- public void close() {
- LOG.trace("Close RoleCtx for Node {}", deviceContext.getDeviceState().getNodeId());
- if (null != entityOwnershipCandidateRegistration) {
- LOG.info("Close Node Entity {} registration", entity);
- entityOwnershipCandidateRegistration.close();
- entityOwnershipCandidateRegistration = null;
- }
- if (null != txEntityOwnershipCandidateRegistration) {
- LOG.info("Close Tx Entity {} registration", txEntity);
- txEntityOwnershipCandidateRegistration.close();
- txEntityOwnershipCandidateRegistration = null;
- }
+ public SalRoleService getSalRoleService() {
+ return this.salRoleService;
}
@Override
public Entity getEntity() {
- return entity;
+ return this.entity;
}
@Override
public Entity getTxEntity() {
- return txEntity;
- }
-
- private boolean isDeviceConnected() {
- return ConnectionContext.CONNECTION_STATE.WORKING.equals(
- deviceContext.getPrimaryConnectionContext().getConnectionState());
+ return this.txEntity;
}
- @Nullable
@Override
- public <T> RequestContext<T> createRequestContext() {
- final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.reservedXidForDeviceMessage()) {
- @Override
- public void close() {
- }
- };
- return ret;
- }
-
- @VisibleForTesting
- void setSalRoleService(final SalRoleService salRoleService) {
- this.salRoleService = salRoleService;
+ public NodeId getNodeId() {
+ return nodeId;
}
@Override
- public DeviceState getDeviceState() {
- return deviceContext.getDeviceState();
+ public boolean isMainCandidateRegistered() {
+ return entityOwnershipCandidateRegistration != null;
}
@Override
- public DeviceContext getDeviceContext() {
- return deviceContext;
+ public boolean isTxCandidateRegistered() {
+ return txEntityOwnershipCandidateRegistration != null;
}
- private ListenableFuture<Void> sendRoleChangeToDevice(final OfpRole newRole, final AsyncFunction<RpcResult<SetRoleOutput>, Void> function) {
- LOG.debug("Send new role {} to device {}", newRole, deviceContext.getDeviceState().getNodeId());
- final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
- if (deviceContext.getDeviceState().getFeatures().getVersion() < OFConstants.OFP_VERSION_1_3) {
- LOG.debug("Device OF version {} not support ROLE", deviceContext.getDeviceState().getFeatures().getVersion());
- setRoleOutputFuture = Futures.immediateFuture(RpcResultBuilder.<SetRoleOutput> success().build());
- } else {
- final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
- .setNode(new NodeRef(deviceContext.getDeviceState().getNodeInstanceIdentifier())).build();
- setRoleOutputFuture = salRoleService.setRole(setRoleInput);
- final TimerTask timerTask = new TimerTask() {
-
- @Override
- public void run(final Timeout timeout) throws Exception {
- if (!setRoleOutputFuture.isDone()) {
- LOG.info("New role {} was not propagated to device {} during 10 sec. Close connection immediately.",
- newRole, deviceContext.getDeviceState().getNodeId());
- setRoleOutputFuture.cancel(true);
- }
+ @Override
+ public boolean registerCandidate(final Entity entity_) {
+ boolean permit = false;
+ try {
+ permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS);
+ if(permit) {
+ LOG.debug("Register candidate for entity {}", entity_);
+ if (entity_.equals(this.entity)) {
+ entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_);
+ } else {
+ txEntityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_);
}
- };
- deviceContext.getTimer().newTimeout(timerTask, 10, TimeUnit.SECONDS);
+ } else {
+ return false;
+ }
+ } catch (final CandidateAlreadyRegisteredException e) {
+ LOG.warn("Candidate for entity {} is already registered.", entity_.getType());
+ return false;
+ } catch (final InterruptedException e) {
+ LOG.warn("Cannot acquire semaphore for register entity {} candidate.", entity_.getType());
+ return false;
+ } finally {
+ if (permit) {
+ roleChangeGuard.release();
+ }
}
- return Futures.transform(JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture), function);
+ return true;
}
-
@Override
- public OfpRole getClusterRole() {
- final OfpRole role;
+ public boolean unregisterCandidate(final Entity entity_) {
+ boolean permit = false;
try {
- roleChangeGuard.acquire();
+ permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS);
+ if(permit) {
+ if (entity_.equals(this.entity)) {
+ if (entityOwnershipCandidateRegistration != null) {
+ LOG.debug("Unregister candidate for entity {}", entity_);
+ entityOwnershipCandidateRegistration.close();
+ entityOwnershipCandidateRegistration = null;
+ }
+ } else {
+ if (txEntityOwnershipCandidateRegistration != null) {
+ LOG.debug("Unregister candidate for tx entity {}", entity_);
+ txEntityOwnershipCandidateRegistration.close();
+ txEntityOwnershipCandidateRegistration = null;
+ }
+ }
+ } else {
+ return false;
+ }
} catch (final InterruptedException e) {
- LOG.warn("Unexpected exception in get ClusterRole process for entity {}", entity);
+ LOG.warn("Cannot acquire semaphore for unregister entity {} candidate.", entity_.getType());
+ return false;
} finally {
- role = OfpRole.forValue(clusterRole.getIntValue());
- roleChangeGuard.release();
+ if (permit) {
+ roleChangeGuard.release();
+ }
}
- return role;
+ return true;
}
+ @Override
+ public void close() {
+ unregisterAllCandidates();
+ }
+
+ public boolean isMaster(){
+ return (txEntityOwnershipCandidateRegistration != null && entityOwnershipCandidateRegistration != null);
+ }
}
*/
package org.opendaylight.openflowplugin.impl.role;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
+
+import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
+import org.opendaylight.openflowplugin.impl.services.SalRoleServiceImpl;
+import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Gets invoked from RpcManagerInitial, registers a candidate with EntityOwnershipService.
- * On receipt of the ownership notification, makes an rpc call to SalRoleSevice.
+ * On receipt of the ownership notification, makes an rpc call to SalRoleService.
*
* Hands over to StatisticsManager at the end.
*/
-public class RoleManagerImpl implements RoleManager, EntityOwnershipListener {
+public class RoleManagerImpl implements RoleManager, EntityOwnershipListener, ServiceChangeListener {
private static final Logger LOG = LoggerFactory.getLogger(RoleManagerImpl.class);
private DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
private final DataBroker dataBroker;
private final EntityOwnershipService entityOwnershipService;
- private final ConcurrentMap<Entity, RoleContext> contexts = new ConcurrentHashMap<>();
- private final ConcurrentMap<Entity, RoleContext> txContexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<NodeId, RoleContext> contexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<Entity, RoleContext> watchingEntities = new ConcurrentHashMap<>();
private final EntityOwnershipListenerRegistration entityOwnershipListenerRegistration;
private final EntityOwnershipListenerRegistration txEntityOwnershipListenerRegistration;
+ private List<RoleChangeListener> listeners = new ArrayList<>();
+
+ private final LifecycleConductor conductor;
- public RoleManagerImpl(final EntityOwnershipService entityOwnershipService, final DataBroker dataBroker) {
+ public RoleManagerImpl(final EntityOwnershipService entityOwnershipService, final DataBroker dataBroker, final LifecycleConductor lifecycleConductor) {
this.entityOwnershipService = Preconditions.checkNotNull(entityOwnershipService);
this.dataBroker = Preconditions.checkNotNull(dataBroker);
this.entityOwnershipListenerRegistration = Preconditions.checkNotNull(entityOwnershipService.registerListener(RoleManager.ENTITY_TYPE, this));
this.txEntityOwnershipListenerRegistration = Preconditions.checkNotNull(entityOwnershipService.registerListener(TX_ENTITY_TYPE, this));
+ this.conductor = lifecycleConductor;
LOG.debug("Register OpenflowOwnershipListener to all entity ownership changes");
}
}
@Override
- public void onDeviceContextLevelUp(@CheckForNull final DeviceContext deviceContext) throws Exception {
- LOG.trace("Role manager called for device:{}", deviceContext.getPrimaryConnectionContext().getNodeId());
- final RoleContext roleContext = new RoleContextImpl(deviceContext, entityOwnershipService,
- makeEntity(deviceContext.getDeviceState().getNodeId()),
- makeTxEntity(deviceContext.getDeviceState().getNodeId()));
-
- Verify.verify(contexts.putIfAbsent(roleContext.getEntity(), roleContext) == null, "Role context for master Node {} is still not closed.", deviceContext.getDeviceState().getNodeId());
- Verify.verify(!txContexts.containsKey(roleContext.getTxEntity()),
- "Role context for master Node {} is still not closed. TxEntity was not unregistered yet.", deviceContext.getDeviceState().getNodeId());
-
- // if the device context gets closed (mostly on connection close), we would need to cleanup
- deviceContext.addDeviceContextClosedHandler(this);
- roleContext.initializationRoleContext();
- deviceInitializationPhaseHandler.onDeviceContextLevelUp(deviceContext);
+ public void onDeviceContextLevelUp(@CheckForNull final NodeId nodeId) throws Exception {
+ final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
+ final RoleContext roleContext = new RoleContextImpl(nodeId, entityOwnershipService, makeEntity(nodeId), makeTxEntity(nodeId), conductor);
+ roleContext.setSalRoleService(new SalRoleServiceImpl(roleContext, deviceContext));
+ Verify.verify(contexts.putIfAbsent(nodeId, roleContext) == null, "Role context for master Node %s is still not closed.", nodeId);
+ makeDeviceRoleChange(OfpRole.BECOMESLAVE, roleContext, true);
+ notifyListenersRoleInitializationDone(roleContext.getNodeId(), roleContext.initialization());
+ watchingEntities.put(roleContext.getEntity(), roleContext);
+ deviceInitializationPhaseHandler.onDeviceContextLevelUp(nodeId);
}
@Override
public void close() {
+ LOG.debug("Close method on role manager was called.");
entityOwnershipListenerRegistration.close();
txEntityOwnershipListenerRegistration.close();
for (final Iterator<RoleContext> iterator = Iterators.consumingIterator(contexts.values().iterator()); iterator.hasNext();) {
// got here because last known role is LEADER and DS might need clearing up
- final RoleContext roleCtx = iterator.next();
- final NodeId nodeId = roleCtx.getDeviceState().getNodeId();
- if (OfpRole.BECOMEMASTER.equals(roleCtx.getClusterRole())) {
- LOG.debug("Last role is LEADER and ownershipService returned hasOwner=false for node: {}; "
- + "cleaning DS as being probably the last owner", nodeId);
- removeDeviceFromOperDS(roleCtx);
+ final RoleContext roleContext = iterator.next();
+ watchingEntities.remove(roleContext.getEntity());
+ watchingEntities.remove(roleContext.getTxEntity());
+ contexts.remove(roleContext.getNodeId());
+ if (roleContext.isTxCandidateRegistered()) {
+ LOG.info("Node {} was holder txEntity, so trying to remove device from operational DS.");
+ removeDeviceFromOperationalDS(roleContext.getNodeId());
} else {
- // NOOP - there is another owner
- LOG.debug("Last role is LEADER and ownershipService returned hasOwner=true for node: {}; "
- + "leaving DS untouched", nodeId);
+ roleContext.close();
}
- txContexts.remove(roleCtx.getTxEntity(), roleCtx);
- roleCtx.close();
}
}
@Override
public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
- final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
+ final NodeId nodeId = deviceContext.getPrimaryConnectionContext().getNodeId();
LOG.trace("onDeviceContextLevelDown for node {}", nodeId);
- final Entity entity = makeEntity(nodeId);
- final RoleContext roleContext = contexts.get(entity);
+ final RoleContext roleContext = contexts.get(nodeId);
if (roleContext != null) {
- LOG.debug("Found roleContext associated to deviceContext: {}, now closing the roleContext", nodeId);
- roleContext.terminationRoleContext();
- final TimerTask timerTask = new TimerTask() {
-
- @Override
- public void run(final Timeout timeout) throws Exception {
- final RoleContext foundMainRoleCtx = contexts.get(roleContext.getEntity());
- final RoleContext foundTxRoleCtx = txContexts.get(roleContext.getTxEntity());
-
- if (roleContext.equals(foundMainRoleCtx)) {
- LOG.info("OldRoleCtx was not remove for entity {} from contexts", roleContext.getEntity());
- contexts.remove(roleContext.getEntity(), roleContext);
- foundMainRoleCtx.close();
- }
-
- if (roleContext.equals(foundTxRoleCtx)) {
- LOG.info("OldRoleCtx was not remove for txEntity {} from contexts", roleContext.getTxEntity());
- txContexts.remove(roleContext.getTxEntity(), roleContext);
- foundTxRoleCtx.close();
- }
- }
- };
- deviceContext.getTimer().newTimeout(timerTask, 10, TimeUnit.SECONDS);
+ LOG.debug("Found roleContext associated to deviceContext: {}, now trying close the roleContext", nodeId);
+ if (roleContext.isMainCandidateRegistered()) {
+ roleContext.unregisterCandidate(roleContext.getEntity());
+ } else {
+ contexts.remove(nodeId, roleContext);
+ roleContext.close();
+ }
}
deviceTerminationPhaseHandler.onDeviceContextLevelDown(deviceContext);
}
- private static Entity makeEntity(final NodeId nodeId) {
+ @VisibleForTesting
+ static Entity makeEntity(final NodeId nodeId) {
return new Entity(RoleManager.ENTITY_TYPE, nodeId.getValue());
}
- private static Entity makeTxEntity(final NodeId nodeId) {
+ @VisibleForTesting
+ static Entity makeTxEntity(final NodeId nodeId) {
return new Entity(RoleManager.TX_ENTITY_TYPE, nodeId.getValue());
}
@Override
public void ownershipChanged(final EntityOwnershipChange ownershipChange) {
+
Preconditions.checkArgument(ownershipChange != null);
- RoleContext roleContext = null;
- try {
- roleContext = contexts.get(ownershipChange.getEntity());
- if (roleContext != null) {
- changeOwnershipForMainEntity(ownershipChange, roleContext);
- return;
- }
+ final RoleContext roleContext = watchingEntities.get(ownershipChange.getEntity());
+
+ LOG.debug("Received EOS message: wasOwner:{} isOwner:{} hasOwner:{} for entity type {} and node {}",
+ ownershipChange.wasOwner(), ownershipChange.isOwner(), ownershipChange.hasOwner(),
+ ownershipChange.getEntity().getType(),
+ roleContext != null ? roleContext.getNodeId() : "-> no watching entity, disregarding notification <-");
- roleContext = txContexts.get(ownershipChange.getEntity());
- if (roleContext != null) {
+ if (roleContext != null) {
+ if (ownershipChange.getEntity().equals(roleContext.getEntity())) {
+ changeOwnershipForMainEntity(ownershipChange, roleContext);
+ } else {
changeOwnershipForTxEntity(ownershipChange, roleContext);
- return;
- }
- } catch (final Exception e) {
- LOG.warn("fail to acquire semaphore: {}", ownershipChange.getEntity(), e);
- if (roleContext != null) {
- roleContext.getDeviceContext().shutdownConnection();
}
+ } else {
+ LOG.debug("OwnershipChange {}", ownershipChange);
}
- LOG.debug("We are not able to find Entity {} ownershipChange {} - disregarding ownership notification",
- ownershipChange.getEntity(), ownershipChange);
}
- private void changeOwnershipForMainEntity(final EntityOwnershipChange ownershipChange,
- @CheckForNull final RoleContext roleContext) {
+ @VisibleForTesting
+ void changeOwnershipForMainEntity(final EntityOwnershipChange ownershipChange, final RoleContext roleContext) {
- LOG.debug("Received Main-EntityOwnershipChange:{}", ownershipChange);
- Preconditions.checkArgument(roleContext != null);
if (roleContext.isMainCandidateRegistered()) {
- LOG.debug("Main-EntityOwnershipRegistration is active for entity {}", ownershipChange.getEntity());
+ LOG.debug("Main-EntityOwnershipRegistration is active for entity type {} and node {}",
+ ownershipChange.getEntity().getType(), roleContext.getNodeId());
if (!ownershipChange.wasOwner() && ownershipChange.isOwner()) {
// SLAVE -> MASTER
- txContexts.put(roleContext.getTxEntity(), roleContext);
- roleContext.onDeviceTryToTakeClusterLeadership();
+ LOG.debug("SLAVE to MASTER for node {}", roleContext.getNodeId());
+ if (roleContext.registerCandidate(roleContext.getTxEntity())) {
+ LOG.debug("Starting watching tx entity for node {}", roleContext.getNodeId());
+ watchingEntities.putIfAbsent(roleContext.getTxEntity(), roleContext);
+ }
} else if (ownershipChange.wasOwner() && !ownershipChange.isOwner()) {
// MASTER -> SLAVE
- roleContext.onDeviceLostClusterLeadership();
- } else if (LOG.isDebugEnabled()) {
- LOG.debug("Not processed Ownership Main Entity {} Event {}", ownershipChange.getEntity(), ownershipChange);
+ LOG.debug("MASTER to SLAVE for node {}", roleContext.getNodeId());
+ conductor.addOneTimeListenerWhenServicesChangesDone(this, roleContext.getNodeId());
+ makeDeviceRoleChange(OfpRole.BECOMESLAVE, roleContext, false);
}
} else {
- LOG.debug("Main-EntityOwnershipRegistration is not active for entity {}", ownershipChange.getEntity());
- contexts.remove(ownershipChange.getEntity(), roleContext);
- if (!ownershipChange.hasOwner() && !ownershipChange.isOwner() && ownershipChange.wasOwner()) {
- /* Method has to clean all context and registrations */
- unregistrationHelper(ownershipChange, roleContext);
+ LOG.debug("Main-EntityOwnershipRegistration is not active for entity type {} and node {}",
+ ownershipChange.getEntity(), roleContext.getNodeId());
+ watchingEntities.remove(ownershipChange.getEntity(), roleContext);
+ if (roleContext.isTxCandidateRegistered()) {
+ LOG.debug("tx candidate still registered for node {}, probably connection lost, trying to unregister tx candidate", roleContext.getNodeId());
+ roleContext.unregisterCandidate(roleContext.getTxEntity());
+ if (ownershipChange.wasOwner() && !ownershipChange.isOwner() && !ownershipChange.hasOwner()) {
+ LOG.debug("Trying to remove from operational node: {}", roleContext.getNodeId());
+ removeDeviceFromOperationalDS(roleContext.getNodeId());
+ }
} else {
- txContexts.remove(roleContext.getTxEntity(), roleContext);
+ final NodeId nodeId = roleContext.getNodeId();
+ contexts.remove(nodeId, roleContext);
roleContext.close();
+ conductor.closeConnection(nodeId);
}
}
}
- private void changeOwnershipForTxEntity(final EntityOwnershipChange ownershipChange,
+ @VisibleForTesting
+ void changeOwnershipForTxEntity(final EntityOwnershipChange ownershipChange,
@Nonnull final RoleContext roleContext) {
- LOG.debug("Received TX-EntityOwnershipChange:{}", ownershipChange);
- Preconditions.checkArgument(roleContext != null);
if (roleContext.isTxCandidateRegistered()) {
- LOG.debug("Tx-EntityOwnershipRegistration is active for entity {}", ownershipChange.getEntity());
+ LOG.debug("Tx-EntityOwnershipRegistration is active for entity type {} and node {}",
+ ownershipChange.getEntity().getType(),
+ roleContext.getNodeId());
if (!ownershipChange.wasOwner() && ownershipChange.isOwner()) {
// SLAVE -> MASTER
- roleContext.onDeviceTakeClusterLeadership();
+ LOG.debug("SLAVE to MASTER for node {}", roleContext.getNodeId());
+ makeDeviceRoleChange(OfpRole.BECOMEMASTER, roleContext,false);
} else if (ownershipChange.wasOwner() && !ownershipChange.isOwner()) {
// MASTER -> SLAVE
- LOG.warn("Tx-EntityOwnershipRegistration unexpected lost Leadership entity {}", ownershipChange.getEntity());
- roleContext.getDeviceContext().shutdownConnection();
- } else {
- LOG.debug("NOOP state transition for TxEntity {} ", roleContext.getTxEntity());
+ LOG.debug("MASTER to SLAVE for node {}", roleContext.getNodeId());
+ LOG.warn("Tx-EntityOwnershipRegistration lost leadership entity type {} and node {}",
+ ownershipChange.getEntity().getType(),roleContext.getNodeId());
+ watchingEntities.remove(roleContext.getTxEntity(), roleContext);
+ watchingEntities.remove(roleContext.getEntity(), roleContext);
+ roleContext.unregisterCandidate(roleContext.getEntity());
+ roleContext.unregisterCandidate(roleContext.getTxEntity());
+ if (!ownershipChange.hasOwner()) {
+ LOG.debug("Trying to remove from operational node: {}", roleContext.getNodeId());
+ removeDeviceFromOperationalDS(roleContext.getNodeId());
+ } else {
+ final NodeId nodeId = roleContext.getNodeId();
+ contexts.remove(nodeId, roleContext);
+ roleContext.close();
+ conductor.closeConnection(nodeId);
+ }
}
} else {
- LOG.debug("Tx-EntityOwnershipRegistration is not active for entity {}", ownershipChange.getEntity());
- txContexts.remove(ownershipChange.getEntity(), roleContext);
+ LOG.debug("Tx-EntityOwnershipRegistration is not active for entity {}", ownershipChange.getEntity().getType());
+ watchingEntities.remove(roleContext.getTxEntity(), roleContext);
+ final NodeId nodeId = roleContext.getNodeId();
+ contexts.remove(nodeId, roleContext);
+ roleContext.close();
+ conductor.closeConnection(nodeId);
}
}
- private CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperDS(
- final RoleChangeListener roleChangeListener) {
- Preconditions.checkArgument(roleChangeListener != null);
- final DeviceState deviceState = roleChangeListener.getDeviceState();
- final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
- delWtx.delete(LogicalDatastoreType.OPERATIONAL, deviceState.getNodeInstanceIdentifier());
- final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
- Futures.addCallback(delFuture, new FutureCallback<Void>() {
-
+ @VisibleForTesting
+ void makeDeviceRoleChange(final OfpRole role, final RoleContext roleContext, final Boolean init) {
+ final ListenableFuture<RpcResult<SetRoleOutput>> roleChangeFuture = sendRoleChangeToDevice(role, roleContext);
+ Futures.addCallback(roleChangeFuture, new FutureCallback<RpcResult<SetRoleOutput>>() {
@Override
- public void onSuccess(final Void result) {
- LOG.debug("Delete Node {} was successful", deviceState.getNodeId());
+ public void onSuccess(@Nullable final RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
+ LOG.info("Role {} successfully set on device {}", role, roleContext.getNodeId());
+ notifyListenersRoleChangeOnDevice(roleContext.getNodeId(), true, role, init);
}
@Override
- public void onFailure(final Throwable t) {
- LOG.warn("Delete Node {} failed.", deviceState.getNodeId(), t);
+ public void onFailure(@Nonnull final Throwable throwable) {
+ LOG.warn("Unable to set role {} on device {}", role, roleContext.getNodeId());
+ notifyListenersRoleChangeOnDevice(roleContext.getNodeId(), false, role, init);
}
});
- return delFuture;
}
- private void unregistrationHelper(final EntityOwnershipChange ownershipChange, final RoleContext roleContext) {
- LOG.info("Initiate removal from operational. Possibly the last node to be disconnected for :{}. ",
- ownershipChange);
- Futures.addCallback(removeDeviceFromOperDS(roleContext), new FutureCallback<Void>() {
+
+ private ListenableFuture<RpcResult<SetRoleOutput>> sendRoleChangeToDevice(final OfpRole newRole, final RoleContext roleContext) {
+ LOG.debug("Sending new role {} to device {}", newRole, roleContext.getNodeId());
+ final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
+ final Short version = conductor.gainVersionSafely(roleContext.getNodeId());
+ if (null == version) {
+ LOG.debug("Device version is null");
+ return Futures.immediateFuture(null);
+ }
+ if (version < OFConstants.OFP_VERSION_1_3) {
+ LOG.debug("Device version not support ROLE");
+ return Futures.immediateFuture(null);
+ } else {
+ final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
+ .setNode(new NodeRef(DeviceStateUtil.createNodeInstanceIdentifier(roleContext.getNodeId()))).build();
+ setRoleOutputFuture = roleContext.getSalRoleService().setRole(setRoleInput);
+ final TimerTask timerTask = new TimerTask() {
+
+ @Override
+ public void run(final Timeout timeout) throws Exception {
+ if (!setRoleOutputFuture.isDone()) {
+ LOG.warn("New role {} was not propagated to device {} during 10 sec", newRole, roleContext.getNodeId());
+ setRoleOutputFuture.cancel(true);
+ }
+ }
+ };
+ conductor.newTimeout(timerTask, 10, TimeUnit.SECONDS);
+ }
+ return JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture);
+ }
+
+ @VisibleForTesting
+ CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final NodeId nodeId) {
+
+ final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
+ delWtx.delete(LogicalDatastoreType.OPERATIONAL, DeviceStateUtil.createNodeInstanceIdentifier(nodeId));
+ final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
+ Futures.addCallback(delFuture, new FutureCallback<Void>() {
+
@Override
- public void onSuccess(final Void aVoid) {
- LOG.debug("Removing context for device: {}", roleContext.getDeviceState().getNodeId());
- txContexts.remove(roleContext.getTxEntity(), roleContext);
- roleContext.close();
+ public void onSuccess(final Void result) {
+ LOG.debug("Delete Node {} was successful", nodeId);
+ final RoleContext roleContext = contexts.remove(nodeId);
+ if (roleContext != null) {
+ roleContext.close();
+ }
}
@Override
- public void onFailure(final Throwable throwable) {
- LOG.warn("Removing role context for device: {}, but {}", roleContext.getDeviceState().getNodeId(),
- throwable.getMessage());
- txContexts.remove(roleContext.getTxEntity(), roleContext);
- roleContext.close();
+ public void onFailure(@Nonnull final Throwable t) {
+ LOG.warn("Delete Node {} failed. {}", nodeId, t);
+ contexts.remove(nodeId);
+ final RoleContext roleContext = contexts.remove(nodeId);
+ if (roleContext != null) {
+ roleContext.close();
+ }
}
});
+ return delFuture;
}
@Override
public void setDeviceTerminationPhaseHandler(final DeviceTerminationPhaseHandler handler) {
deviceTerminationPhaseHandler = handler;
}
+
+ @Override
+ public void servicesChangeDone(final NodeId nodeId, final boolean success) {
+ LOG.debug("Services stopping done for node {} as " + (success ? "successful" : "unsuccessful"), nodeId);
+ final RoleContext roleContext = contexts.get(nodeId);
+ if (null != roleContext) {
+ /* Services stopped or failure */
+ roleContext.unregisterCandidate(roleContext.getTxEntity());
+ }
+ }
+
+ @VisibleForTesting
+ RoleContext getRoleContext(final NodeId nodeId){
+ return contexts.get(nodeId);
+ }
+
+ @Override
+ public void addRoleChangeListener(final RoleChangeListener roleChangeListener) {
+ this.listeners.add(roleChangeListener);
+ }
+
+ /**
+ * Invoked when initialization phase is done
+ * @param nodeId node identification
+ * @param success true if initialization done ok, false otherwise
+ */
+ @VisibleForTesting
+ void notifyListenersRoleInitializationDone(final NodeId nodeId, final boolean success){
+ LOG.debug("Notifying registered listeners for role initialization done, no. of listeners {}", listeners.size());
+ for (final RoleChangeListener listener : listeners) {
+ listener.roleInitializationDone(nodeId, success);
+ }
+ }
+
+ /**
+ * Notifies registered listener on role change. Role is the new role on device
+ * If initialization phase is true, we may skip service starting
+ * @param success true if role change on device done ok, false otherwise
+ * @param role new role meant to be set on device
+ * @param initializationPhase if true, then skipp services start
+ */
+ @VisibleForTesting
+ void notifyListenersRoleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole role, final boolean initializationPhase){
+ LOG.debug("Notifying registered listeners for role change, no. of listeners {}", listeners.size());
+ for (final RoleChangeListener listener : listeners) {
+ listener.roleChangeOnDevice(nodeId, success, role, initializationPhase);
+ }
+ }
+
}
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicLong;
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.XidSequencer;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RpcContextImpl implements RpcContext {
private static final Logger LOG = LoggerFactory.getLogger(RpcContextImpl.class);
private final RpcProviderRegistry rpcProviderRegistry;
- private final DeviceContext deviceContext;
private final MessageSpy messageSpy;
private final Semaphore tracker;
+ private final XidSequencer xidSequencer;
// TODO: add private Sal salBroker
private final ConcurrentMap<Class<?>, RoutedRpcRegistration<?>> rpcRegistrations = new ConcurrentHashMap<>();
- private final boolean isStatisticsRpcEnabled;
- private final NotificationPublishService notificationPublishService;
+ private final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
- public RpcContextImpl(final MessageSpy messageSpy, final RpcProviderRegistry rpcProviderRegistry, final DeviceContext deviceContext,
- final int maxRequests, final boolean isStatisticsRpcEnabled,
- final NotificationPublishService notificationPublishService) {
- this.deviceContext = Preconditions.checkNotNull(deviceContext);
+ public RpcContextImpl(final RpcProviderRegistry rpcProviderRegistry,
+ final XidSequencer xidSequencer,
+ final MessageSpy messageSpy,
+ final int maxRequests,
+ final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier) {
+ this.xidSequencer = Preconditions.checkNotNull(xidSequencer);
this.messageSpy = Preconditions.checkNotNull(messageSpy);
this.rpcProviderRegistry = Preconditions.checkNotNull(rpcProviderRegistry);
- this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
- this.notificationPublishService = notificationPublishService;
+ this.nodeInstanceIdentifier = nodeInstanceIdentifier;
+
tracker = new Semaphore(maxRequests, true);
- deviceContext.setRpcContext(RpcContextImpl.this);
}
/**
@Override
public <S extends RpcService> void registerRpcServiceImplementation(final Class<S> serviceClass,
final S serviceInstance) {
- LOG.trace("Try to register service {} for device {}.", serviceClass, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ LOG.trace("Try to register service {} for device {}.", serviceClass, nodeInstanceIdentifier);
if (! rpcRegistrations.containsKey(serviceClass)) {
final RoutedRpcRegistration<S> routedRpcReg = rpcProviderRegistry.addRoutedRpcImplementation(serviceClass, serviceInstance);
- routedRpcReg.registerPath(NodeContext.class, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ routedRpcReg.registerPath(NodeContext.class, nodeInstanceIdentifier);
rpcRegistrations.put(serviceClass, routedRpcReg);
- LOG.debug("Registration of service {} for device {}.", serviceClass, deviceContext.getDeviceState().getNodeInstanceIdentifier());
- }
- }
-
- @Override
- public void registerStatCompatibilityServices() {
- if (isStatisticsRpcEnabled) {
- MdSalRegistrationUtils.registerStatCompatibilityServices(RpcContextImpl.this, deviceContext,
- notificationPublishService, new AtomicLong());
+ LOG.debug("Registration of service {} for device {}.", serviceClass, nodeInstanceIdentifier);
}
}
final RpcService rpcService = rpcRegistrations.get(serviceClass).getInstance();
return (S) rpcService;
}
+
/**
* Unregisters all services.
*
for (final Iterator<Entry<Class<?>, RoutedRpcRegistration<?>>> iterator = Iterators
.consumingIterator(rpcRegistrations.entrySet().iterator()); iterator.hasNext();) {
final RoutedRpcRegistration<?> rpcRegistration = iterator.next().getValue();
- rpcRegistration.unregisterPath(NodeContext.class, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ rpcRegistration.unregisterPath(NodeContext.class, nodeInstanceIdentifier);
rpcRegistration.close();
LOG.debug("Closing RPC Registration of service {} for device {}.", rpcRegistration.getServiceType(),
- deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ nodeInstanceIdentifier);
}
}
LOG.trace("Device queue {} at capacity", this);
return null;
} else {
- LOG.trace("Acquired semaphore for {}, available permits:{} ", deviceContext.getDeviceState().getNodeId(), tracker.availablePermits());
+ LOG.trace("Acquired semaphore for {}, available permits:{} ", nodeInstanceIdentifier.getKey().getId(), tracker.availablePermits());
}
- final Long xid = deviceContext.reservedXidForDeviceMessage();
+ final Long xid = xidSequencer.reserveXidForDeviceMessage();
if (xid == null) {
- LOG.warn("Xid cannot be reserved for new RequestContext, node:{}", deviceContext.getDeviceState().getNodeId());
+ LOG.warn("Xid cannot be reserved for new RequestContext, node:{}", nodeInstanceIdentifier.getKey().getId());
tracker.release();
return null;
}
@Override
public <S extends RpcService> void unregisterRpcServiceImplementation(final Class<S> serviceClass) {
- LOG.trace("Try to unregister serviceClass {} for Node {}", serviceClass, deviceContext.getDeviceState().getNodeId());
+ LOG.trace("Try to unregister serviceClass {} for Node {}", serviceClass, nodeInstanceIdentifier.getKey().getId());
final RoutedRpcRegistration<?> rpcRegistration = rpcRegistrations.remove(serviceClass);
if (rpcRegistration != null) {
- rpcRegistration.unregisterPath(NodeContext.class, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+ rpcRegistration.unregisterPath(NodeContext.class, nodeInstanceIdentifier);
rpcRegistration.close();
- LOG.debug("Unregistration serviceClass {} for Node {}", serviceClass, deviceContext.getDeviceState().getNodeId());
+ LOG.debug("Unregistration serviceClass {} for Node {}", serviceClass, nodeInstanceIdentifier.getKey().getId());
}
}
}
*/
package org.opendaylight.openflowplugin.impl.rpc;
+import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.Iterators;
import java.util.Iterator;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
-import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
private final int maxRequestsQuota;
private final ConcurrentMap<NodeId, RpcContext> contexts = new ConcurrentHashMap<>();
- private boolean isStatisticsRpcEnabled;
- private NotificationPublishService notificationPublishService;
+
+ private final LifecycleConductor conductor;
public RpcManagerImpl(final RpcProviderRegistry rpcProviderRegistry,
- final int quotaValue) {
+ final int quotaValue,
+ final LifecycleConductor lifecycleConductor) {
this.rpcProviderRegistry = rpcProviderRegistry;
maxRequestsQuota = quotaValue;
+ this.conductor = lifecycleConductor;
}
@Override
}
@Override
- public void onDeviceContextLevelUp(final DeviceContext deviceContext) throws Exception {
- final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
- final OfpRole ofpRole = deviceContext.getDeviceState().getRole();
+ public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
- LOG.debug("Node:{}, deviceContext.getDeviceState().getRole():{}", nodeId, ofpRole);
- final RpcContext rpcContext = new RpcContextImpl(deviceContext.getMessageSpy(), rpcProviderRegistry,
- deviceContext, maxRequestsQuota, isStatisticsRpcEnabled, notificationPublishService);
+ final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
- Verify.verify(contexts.putIfAbsent(nodeId, rpcContext) == null, "RpcCtx still not closed for node {}", nodeId);
- deviceContext.addDeviceContextClosedHandler(this);
+ final RpcContext rpcContext = new RpcContextImpl(
+ rpcProviderRegistry,
+ deviceContext,
+ deviceContext.getMessageSpy(),
+ maxRequestsQuota,
+ deviceContext.getDeviceState().getNodeInstanceIdentifier());
- if (OfpRole.BECOMEMASTER.equals(ofpRole)) {
- LOG.info("Registering Openflow Master RPCs for node:{}, role:{}", nodeId, ofpRole);
- MdSalRegistrationUtils.registerMasterServices(rpcContext, deviceContext, ofpRole);
+ deviceContext.setRpcContext(rpcContext);
- } else if(OfpRole.BECOMESLAVE.equals(ofpRole)) {
- // if slave, we need to de-register rpcs if any have been registered, in case of master to slave
- LOG.info("Unregister RPC services (if any) for slave role for node:{}", deviceContext.getDeviceState().getNodeId());
- MdSalRegistrationUtils.registerSlaveServices(rpcContext, ofpRole);
- } else {
- // if we don't know role, we need to unregister rpcs if any have been registered
- LOG.info("Unregister RPC services (if any) for slave role for node:{}", deviceContext.getDeviceState().getNodeId());
- MdSalRegistrationUtils.unregisterServices(rpcContext);
- }
+ Verify.verify(contexts.putIfAbsent(nodeId, rpcContext) == null, "RpcCtx still not closed for node {}", nodeId);
// finish device initialization cycle back to DeviceManager
- deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
+ deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
}
@Override
}
}
-
@Override
public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
final RpcContext removedContext = contexts.remove(deviceContext.getDeviceState().getNodeId());
}
deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceContext);
}
- @Override
- public void setStatisticsRpcEnabled(final boolean isStatisticsRpcEnabled) {
- this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
- }
-
- @Override
- public void setNotificationPublishService(final NotificationPublishService notificationPublishService) {
- this.notificationPublishService = notificationPublishService;
- }
@Override
public void setDeviceTerminationPhaseHandler(final DeviceTerminationPhaseHandler handler) {
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* General implementation of {@link ItemLifecycleListener} - keeping of DS/operational reflection up-to-date
*/
public class ItemLifecycleListenerImpl implements ItemLifecycleListener {
+ private static final Logger LOG = LoggerFactory.getLogger(ItemLifecycleListenerImpl.class);
+
private final DeviceContext deviceContext;
public ItemLifecycleListenerImpl(DeviceContext deviceContext) {
@Override
public <I extends Identifiable<K> & DataObject, K extends Identifier<I>> void onAdded(KeyedInstanceIdentifier<I, K> itemPath, I itemBody) {
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, itemPath, itemBody);
- deviceContext.submitTransaction();
+ try {
+ deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, itemPath, itemBody);
+ deviceContext.submitTransaction();
+ } catch (Exception e) {
+ LOG.warn("Not able to write to transaction: {}", e.getMessage());
+ }
}
@Override
public <I extends Identifiable<K> & DataObject, K extends Identifier<I>> void onRemoved(KeyedInstanceIdentifier<I, K> itemPath) {
- deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, itemPath);
- deviceContext.submitTransaction();
+ try {
+ deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, itemPath);
+ deviceContext.submitTransaction();
+ } catch (Exception e) {
+ LOG.warn("Not able to write to transaction: {}", e.getMessage());
+ }
}
}
final UpdateTableOutputBuilder updateTableOutputBuilder = new UpdateTableOutputBuilder();
updateTableOutputBuilder.setTransactionId(new TransactionId(BigInteger.valueOf(xid)));
finalFuture.set(RpcResultBuilder.success(updateTableOutputBuilder.build()).build());
- writeResponseToOperationalDatastore(multipartReplies);
+ try {
+ writeResponseToOperationalDatastore(multipartReplies);
+ } catch (Exception e) {
+ LOG.warn("Not able to write to operational datastore: {}", e.getMessage());
+ }
}
} else {
LOG.debug("OnSuccess, rpc result unsuccessful, multipart response for rpc update-table was unsuccessful.");
/**
* @param multipartReplies
*/
- private void writeResponseToOperationalDatastore(final List<MultipartReply> multipartReplies) {
+ private void writeResponseToOperationalDatastore(final List<MultipartReply> multipartReplies) throws Exception {
final List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> salTableFeatures = convertToSalTableFeatures(multipartReplies);
import java.util.Iterator;
import java.util.List;
import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
import org.opendaylight.openflowplugin.impl.services.RequestContextUtil;
import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService;
import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * Created by Martin Bobak <mbobak@cisco.com> on 1.4.2015.
- */
public class StatisticsContextImpl implements StatisticsContext {
private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class);
private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService;
private Timeout pollTimeout;
- public StatisticsContextImpl(@CheckForNull final DeviceContext deviceContext,
- final boolean shuttingDownStatisticsPolling) {
- this.deviceContext = Preconditions.checkNotNull(deviceContext);
+ private final LifecycleConductor conductor;
+
+ public StatisticsContextImpl(@CheckForNull final NodeId nodeId, final boolean shuttingDownStatisticsPolling, final LifecycleConductor lifecycleConductor) {
+ this.conductor = lifecycleConductor;
+ this.deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
this.devState = Preconditions.checkNotNull(deviceContext.getDeviceState());
this.shuttingDownStatisticsPolling = shuttingDownStatisticsPolling;
- emptyFuture = Futures.immediateFuture(new Boolean(false));
+ emptyFuture = Futures.immediateFuture(false);
statisticsGatheringService = new StatisticsGatheringService(this, deviceContext);
statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext);
itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext);
@Override
public <T> RequestContext<T> createRequestContext() {
- final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.reservedXidForDeviceMessage()) {
+ final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.reserveXidForDeviceMessage()) {
@Override
public void close() {
requestContexts.remove(this);
}
}
- @Override
- public void setPollTimeout (Timeout pollTimeout){
- this.pollTimeout = pollTimeout;
- }
+ @Override
+ public void setPollTimeout(final Timeout pollTimeout) {
+ this.pollTimeout = pollTimeout;
+ }
- @Override
- public Optional<Timeout> getPollTimeout () {
- return Optional.fromNullable(pollTimeout);
+ @Override
+ public Optional<Timeout> getPollTimeout() {
+ return Optional.fromNullable(pollTimeout);
+ }
+
+ private void statChainFuture(final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture) {
+ if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
+ final String errMsg = String.format("Device connection is closed for Node : %s.",
+ deviceContext.getDeviceState().getNodeId());
+ LOG.debug(errMsg);
+ resultFuture.setException(new IllegalStateException(errMsg));
+ return;
+ }
+ if ( ! iterator.hasNext()) {
+ resultFuture.set(Boolean.TRUE);
+ LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceState().getNodeId());
+ return;
}
- void statChainFuture ( final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture){
+ final MultipartType nextType = iterator.next();
+ LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceState().getNodeId(), nextType);
- if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
- final String errMsg = String.format("Device connection is closed for Node : %s.",
- deviceContext.getDeviceState().getNodeId());
- LOG.debug(errMsg);
- resultFuture.setException(new IllegalStateException(errMsg));
- return;
+ final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(nextType);
+ Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(final Boolean result) {
+ statChainFuture(iterator, resultFuture);
}
-
- if (!iterator.hasNext()) {
- resultFuture.set(Boolean.TRUE);
- LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceState().getNodeId());
- return;
+ @Override
+ public void onFailure(@Nonnull final Throwable t) {
+ resultFuture.setException(t);
}
+ });
+ }
- final MultipartType nextType = iterator.next();
- LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceState().getNodeId(), nextType);
-
- final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(nextType);
- Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
- @Override
- public void onSuccess(final Boolean result) {
- statChainFuture(iterator, resultFuture);
- }
-
- @Override
- public void onFailure(final Throwable t) {
- resultFuture.setException(t);
- }
- });
- }
-
- /**
- * Method checks a device state. It returns null for be able continue. Otherwise it returns immediateFuture
- * which has to be returned from caller too
- *
- * @return
- */
- @VisibleForTesting
- ListenableFuture<Boolean> deviceConnectionCheck () {
- if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
- ListenableFuture<Boolean> resultingFuture = SettableFuture.create();
- switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) {
- case RIP:
- final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s",
- deviceContext.getPrimaryConnectionContext().getConnectionState());
- resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg));
- break;
- default:
- resultingFuture = Futures.immediateCheckedFuture(Boolean.TRUE);
- break;
- }
- return resultingFuture;
+ /**
+ * Method checks a device state. It returns null for be able continue. Otherwise it returns immediateFuture
+ * which has to be returned from caller too
+ *
+ * @return
+ */
+ @VisibleForTesting
+ ListenableFuture<Boolean> deviceConnectionCheck() {
+ if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
+ ListenableFuture<Boolean> resultingFuture = SettableFuture.create();
+ switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) {
+ case RIP:
+ final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s",
+ deviceContext.getPrimaryConnectionContext().getConnectionState());
+ resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg));
+ break;
+ default:
+ resultingFuture = Futures.immediateCheckedFuture(Boolean.TRUE);
+ break;
}
- return null;
+ return resultingFuture;
}
+ return null;
+ }
- private ListenableFuture<Boolean> collectFlowStatistics ( final MultipartType multipartType){
- return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectFlowStatistics(final MultipartType multipartType) {
+ return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture;
+ }
- private ListenableFuture<Boolean> collectTableStatistics ( final MultipartType multipartType){
- return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectTableStatistics(final MultipartType multipartType) {
+ return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture;
+ }
- private ListenableFuture<Boolean> collectPortStatistics ( final MultipartType multipartType){
- return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectPortStatistics(final MultipartType multipartType) {
+ return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture;
+ }
- private ListenableFuture<Boolean> collectQueueStatistics ( final MultipartType multipartType){
- return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectQueueStatistics(final MultipartType multipartType) {
+ return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture;
+ }
- private ListenableFuture<Boolean> collectGroupDescStatistics ( final MultipartType multipartType){
- return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectGroupDescStatistics(final MultipartType multipartType) {
+ return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture;
+ }
- private ListenableFuture<Boolean> collectGroupStatistics ( final MultipartType multipartType){
- return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectGroupStatistics(final MultipartType multipartType) {
+ return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture;
+ }
- private ListenableFuture<Boolean> collectMeterConfigStatistics ( final MultipartType multipartType){
- return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectMeterConfigStatistics(final MultipartType multipartType) {
+ return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture;
+ }
- private ListenableFuture<Boolean> collectMeterStatistics ( final MultipartType multipartType){
- return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
- statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture;
- }
+ private ListenableFuture<Boolean> collectMeterStatistics(final MultipartType multipartType) {
+ return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+ statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture;
+ }
@VisibleForTesting
- protected void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) {
+ void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) {
this.statisticsGatheringService = statisticsGatheringService;
}
@VisibleForTesting
- protected void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService
+ void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService
statisticsGatheringOnTheFlyService) {
this.statisticsGatheringOnTheFlyService = statisticsGatheringOnTheFlyService;
}
});
}
- private static void processMeterConfigStatsUpdated(final Iterable<MeterConfigStatsUpdated> data, final DeviceContext deviceContext) {
+ private static void processMeterConfigStatsUpdated(final Iterable<MeterConfigStatsUpdated> data, final DeviceContext deviceContext) throws Exception {
final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
deleteAllKnownMeters(deviceContext, fNodeIdent);
for (final MeterConfigStatsUpdated meterConfigStatsUpdated : data) {
public static void writeFlowStatistics(final Iterable<FlowsStatisticsUpdate> data, final DeviceContext deviceContext) {
final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
- for (final FlowsStatisticsUpdate flowsStatistics : data) {
- for (final FlowAndStatisticsMapList flowStat : flowsStatistics.getFlowAndStatisticsMapList()) {
- final FlowBuilder flowBuilder = new FlowBuilder(flowStat);
- flowBuilder.addAugmentation(FlowStatisticsData.class, refineFlowStatisticsAugmentation(flowStat).build());
-
- final short tableId = flowStat.getTableId();
- final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
- final FlowId flowId = deviceContext.getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
-
- final FlowKey flowKey = new FlowKey(flowId);
- flowBuilder.setKey(flowKey);
- final TableKey tableKey = new TableKey(tableId);
- final InstanceIdentifier<Flow> flowIdent = fNodeIdent.child(Table.class, tableKey).child(Flow.class, flowKey);
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build());
+ try {
+ for (final FlowsStatisticsUpdate flowsStatistics : data) {
+ for (final FlowAndStatisticsMapList flowStat : flowsStatistics.getFlowAndStatisticsMapList()) {
+ final FlowBuilder flowBuilder = new FlowBuilder(flowStat);
+ flowBuilder.addAugmentation(FlowStatisticsData.class, refineFlowStatisticsAugmentation(flowStat).build());
+
+ final short tableId = flowStat.getTableId();
+ final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
+ final FlowId flowId = deviceContext.getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
+
+ final FlowKey flowKey = new FlowKey(flowId);
+ flowBuilder.setKey(flowKey);
+ final TableKey tableKey = new TableKey(tableId);
+ final InstanceIdentifier<Flow> flowIdent = fNodeIdent.child(Table.class, tableKey).child(Flow.class, flowKey);
+ deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build());
+ }
}
+ } catch (Exception e) {
+ LOG.warn("Not able to write to transaction: {}", e.getMessage());
}
}
return Futures.immediateFuture(null);
}
- private static void processQueueStatistics(final Iterable<QueueStatisticsUpdate> data, final DeviceContext deviceContext) {
+ private static void processQueueStatistics(final Iterable<QueueStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
// TODO: clean all queues of all node-connectors before writing up-to-date stats
final InstanceIdentifier<Node> nodeIdent = deviceContext.getDeviceState().getNodeInstanceIdentifier();
for (final QueueStatisticsUpdate queueStatisticsUpdate : data) {
deviceContext.submitTransaction();
}
- private static void processFlowTableStatistics(final Iterable<FlowTableStatisticsUpdate> data, final DeviceContext deviceContext) {
+ private static void processFlowTableStatistics(final Iterable<FlowTableStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
for (final FlowTableStatisticsUpdate flowTableStatisticsUpdate : data) {
deviceContext.submitTransaction();
}
- private static void processNodeConnectorStatistics(final Iterable<NodeConnectorStatisticsUpdate> data, final DeviceContext deviceContext) {
+ private static void processNodeConnectorStatistics(final Iterable<NodeConnectorStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
final InstanceIdentifier<Node> nodeIdent = deviceContext.getDeviceState().getNodeInstanceIdentifier();
for (final NodeConnectorStatisticsUpdate nodeConnectorStatisticsUpdate : data) {
for (final NodeConnectorStatisticsAndPortNumberMap nConnectPort : nodeConnectorStatisticsUpdate.getNodeConnectorStatisticsAndPortNumberMap()) {
}
private static void processMetersStatistics(final Iterable<MeterStatisticsUpdated> data,
- final DeviceContext deviceContext) {
+ final DeviceContext deviceContext) throws Exception {
final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
for (final MeterStatisticsUpdated meterStatisticsUpdated : data) {
for (final MeterStats mStat : meterStatisticsUpdated.getMeterStats()) {
deviceContext.submitTransaction();
}
- private static void deleteAllKnownMeters(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) {
+ private static void deleteAllKnownMeters(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) throws Exception {
for (final MeterId meterId : deviceContext.getDeviceMeterRegistry().getAllMeterIds()) {
final InstanceIdentifier<Meter> meterIdent = fNodeIdent.child(Meter.class, new MeterKey(meterId));
deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, meterIdent);
deviceContext.getDeviceMeterRegistry().removeMarked();
}
- private static void processGroupDescStats(final Iterable<GroupDescStatsUpdated> data, final DeviceContext deviceContext) {
+ private static void processGroupDescStats(final Iterable<GroupDescStatsUpdated> data, final DeviceContext deviceContext) throws Exception {
final InstanceIdentifier<FlowCapableNode> fNodeIdent =
deviceContext.getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
deleteAllKnownGroups(deviceContext, fNodeIdent);
deviceContext.submitTransaction();
}
- private static void deleteAllKnownGroups(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) {
+ private static void deleteAllKnownGroups(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) throws Exception {
for (final GroupId groupId : deviceContext.getDeviceGroupRegistry().getAllGroupIds()) {
final InstanceIdentifier<Group> groupIdent = fNodeIdent.child(Group.class, new GroupKey(groupId));
deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, groupIdent);
deviceContext.getDeviceGroupRegistry().removeMarked();
}
- private static void processGroupStatistics(final Iterable<GroupStatisticsUpdated> data, final DeviceContext deviceContext) {
+ private static void processGroupStatistics(final Iterable<GroupStatisticsUpdated> data, final DeviceContext deviceContext) throws Exception {
final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
for (final GroupStatisticsUpdated groupStatistics : data) {
for (final GroupStats groupStats : groupStatistics.getGroupStats()) {
*
* @param deviceContext txManager + node path keeper
*/
- public static void markDeviceStateSnapshotStart(DeviceContext deviceContext) {
+ static void markDeviceStateSnapshotStart(final DeviceContext deviceContext) {
final InstanceIdentifier<FlowCapableStatisticsGatheringStatus> statusPath = deviceContext.getDeviceState()
.getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class);
.build())
.setSnapshotGatheringStatusEnd(null) // TODO: reconsider if really need to clean end mark here
.build();
+ try {
+ deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusPath, gatheringStatus);
+ } catch (final Exception e) {
+ LOG.warn("Can't write to transaction: {}", e);
+ }
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusPath, gatheringStatus);
deviceContext.submitTransaction();
}
* @param deviceContext txManager + node path keeper
* @param succeeded outcome of currently finished gathering
*/
- public static void markDeviceStateSnapshotEnd(DeviceContext deviceContext, final boolean succeeded) {
+ static void markDeviceStateSnapshotEnd(final DeviceContext deviceContext, final boolean succeeded) {
final InstanceIdentifier<SnapshotGatheringStatusEnd> statusEndPath = deviceContext.getDeviceState()
.getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class)
.child(SnapshotGatheringStatusEnd.class);
.setEnd(new DateAndTime(simpleDateFormat.format(new Date())))
.setSucceeded(succeeded)
.build();
+ try {
+ deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusEndPath, gatheringStatus);
+ } catch (Exception e) {
+ LOG.warn("Can't write to transaction: {}", e);
+ }
- deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusEndPath, gatheringStatus);
deviceContext.submitTransaction();
}
}
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import java.util.Iterator;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-/**
- * Created by Martin Bobak <mbobak@cisco.com> on 1.4.2015.
- */
public class StatisticsManagerImpl implements StatisticsManager, StatisticsManagerControlService {
private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class);
private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
- private HashedWheelTimer hashedWheelTimer;
-
private final ConcurrentMap<NodeId, StatisticsContext> contexts = new ConcurrentHashMap<>();
private static final long basicTimerDelay = 3000;
private boolean shuttingDownStatisticsPolling;
private BindingAwareBroker.RpcRegistration<StatisticsManagerControlService> controlServiceRegistration;
+ private final LifecycleConductor conductor;
+
@Override
public void setDeviceInitializationPhaseHandler(final DeviceInitializationPhaseHandler handler) {
deviceInitPhaseHandler = handler;
}
public StatisticsManagerImpl(@CheckForNull final RpcProviderRegistry rpcProviderRegistry,
- final boolean shuttingDownStatisticsPolling) {
+ final boolean shuttingDownStatisticsPolling,
+ final LifecycleConductor lifecycleConductor) {
Preconditions.checkArgument(rpcProviderRegistry != null);
this.controlServiceRegistration = Preconditions.checkNotNull(rpcProviderRegistry.addRpcImplementation(
StatisticsManagerControlService.class, this));
this.shuttingDownStatisticsPolling = shuttingDownStatisticsPolling;
+ this.conductor = lifecycleConductor;
}
@Override
- public void onDeviceContextLevelUp(final DeviceContext deviceContext) throws Exception {
- final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
- final OfpRole ofpRole = deviceContext.getDeviceState().getRole();
- LOG.debug("Node:{}, deviceContext.getDeviceState().getRole():{}", nodeId, ofpRole);
-
- if (null == hashedWheelTimer) {
- LOG.trace("This is first device that delivered timer. Starting statistics polling immediately.");
- hashedWheelTimer = deviceContext.getTimer();
- }
- final StatisticsContext statisticsContext = new StatisticsContextImpl(deviceContext, shuttingDownStatisticsPolling);
+ public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
+
+ final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
+ final StatisticsContext statisticsContext = new StatisticsContextImpl(nodeId, shuttingDownStatisticsPolling, conductor);
Verify.verify(contexts.putIfAbsent(nodeId, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", nodeId);
- deviceContext.addDeviceContextClosedHandler(this);
if (shuttingDownStatisticsPolling) {
- LOG.info("Statistics is shutdown for node:{}", deviceContext.getDeviceState().getNodeId());
+ LOG.info("Statistics is shutdown for node:{}", nodeId);
} else {
- LOG.info("Schedule Statistics poll for node:{}", deviceContext.getDeviceState().getNodeId());
- if (OfpRole.BECOMEMASTER.equals(ofpRole)) {
- initialStatPollForMaster(statisticsContext, deviceContext);
- /* we want to wait for initial statCollecting response */
- return;
- }
+ LOG.info("Schedule Statistics poll for node:{}", nodeId);
scheduleNextPolling(deviceContext, statisticsContext, new TimeCounter());
}
- deviceContext.getDeviceState().setDeviceSynchronized(true);
- deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
- }
-
- private void initialStatPollForMaster(final StatisticsContext statisticsContext, final DeviceContext deviceContext) {
- final ListenableFuture<Boolean> weHaveDynamicData = statisticsContext.gatherDynamicData();
- Futures.addCallback(weHaveDynamicData, new FutureCallback<Boolean>() {
- @Override
- public void onSuccess(final Boolean statisticsGathered) {
- if (statisticsGathered) {
- //there are some statistics on device worth gathering
- final TimeCounter timeCounter = new TimeCounter();
- deviceContext.getDeviceState().setStatisticsPollingEnabledProp(true);
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
- LOG.trace("Device dynamic info collecting done. Going to announce raise to next level.");
- try {
- deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
- } catch (final Exception e) {
- LOG.info("failed to complete levelUp on next handler for device {}", deviceContext.getDeviceState().getNodeId());
- deviceContext.shutdownConnection();
- return;
- }
- deviceContext.getDeviceState().setDeviceSynchronized(true);
- } else {
- final String deviceAddress = deviceContext.getPrimaryConnectionContext().getConnectionAdapter().getRemoteAddress().toString();
- LOG.info("Statistics for device {} could not be gathered. Closing its device context.", deviceAddress);
- deviceContext.shutdownConnection();
- }
- }
- @Override
- public void onFailure(final Throwable throwable) {
- LOG.warn("Statistics manager was not able to collect dynamic info for device.", deviceContext.getDeviceState().getNodeId(), throwable);
- deviceContext.shutdownConnection();
- }
- });
+ deviceContext.getDeviceState().setDeviceSynchronized(true);
+ deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
}
private void pollStatistics(final DeviceContext deviceContext,
scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
return;
}
+
if (!OfpRole.BECOMEMASTER.equals(deviceContext.getDeviceState().getRole())) {
LOG.debug("Role is not Master so we don't want to poll any stat for device: {}", deviceContext.getDeviceState().getNodeId());
scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
return;
}
-
LOG.debug("POLLING ALL STATS for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
timeCounter.markStart();
final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = statisticsContext.gatherDynamicData();
}
@Override
- public void onFailure(final Throwable throwable) {
+ public void onFailure(@Nonnull final Throwable throwable) {
timeCounter.addTimeMark();
- LOG.info("Statistics gathering for single node was not successful: {}", throwable.getMessage());
- LOG.debug("Statistics gathering for single node was not successful.. ", throwable);
+ LOG.warn("Statistics gathering for single node was not successful: {}", throwable.getMessage());
+ LOG.trace("Statistics gathering for single node was not successful.. ", throwable);
calculateTimerDelay(timeCounter);
- scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ if (throwable instanceof CancellationException) {
+ /** This often happens when something wrong with akka or DS, so closing connection will help to restart device **/
+ conductor.closeConnection(deviceContext.getDeviceState().getNodeId());
+ } else {
+ scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+ }
}
});
- final long averangeTime = TimeUnit.MILLISECONDS.toSeconds(timeCounter.getAverageTimeBetweenMarks());
- final long STATS_TIMEOUT_SEC = averangeTime > 0 ? 3 * averangeTime : DEFAULT_STATS_TIMEOUT_SEC;
+ final long averageTime = TimeUnit.MILLISECONDS.toSeconds(timeCounter.getAverageTimeBetweenMarks());
+ final long STATS_TIMEOUT_SEC = averageTime > 0 ? 3 * averageTime : DEFAULT_STATS_TIMEOUT_SEC;
final TimerTask timerTask = new TimerTask() {
@Override
}
}
};
- deviceContext.getTimer().newTimeout(timerTask, STATS_TIMEOUT_SEC, TimeUnit.SECONDS);
+ conductor.newTimeout(timerTask, STATS_TIMEOUT_SEC, TimeUnit.SECONDS);
}
private void scheduleNextPolling(final DeviceContext deviceContext,
final StatisticsContext statisticsContext,
final TimeCounter timeCounter) {
- if (null != hashedWheelTimer) {
- LOG.debug("SCHEDULING NEXT STATS POLLING for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
- if (!shuttingDownStatisticsPolling) {
- final Timeout pollTimeout = hashedWheelTimer.newTimeout(new TimerTask() {
- @Override
- public void run(final Timeout timeout) throws Exception {
- pollStatistics(deviceContext, statisticsContext, timeCounter);
- }
- }, currentTimerDelay, TimeUnit.MILLISECONDS);
- statisticsContext.setPollTimeout(pollTimeout);
- }
- } else {
- LOG.debug("#!NOT SCHEDULING NEXT STATS POLLING for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
+ LOG.debug("SCHEDULING NEXT STATS POLLING for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
+ if (!shuttingDownStatisticsPolling) {
+ final Timeout pollTimeout = conductor.newTimeout(new TimerTask() {
+ @Override
+ public void run(final Timeout timeout) throws Exception {
+ pollStatistics(deviceContext, statisticsContext, timeCounter);
+ }
+ }, currentTimerDelay, TimeUnit.MILLISECONDS);
+ statisticsContext.setPollTimeout(pollTimeout);
}
}
@VisibleForTesting
- protected void calculateTimerDelay(final TimeCounter timeCounter) {
+ void calculateTimerDelay(final TimeCounter timeCounter) {
final long averageStatisticsGatheringTime = timeCounter.getAverageTimeBetweenMarks();
if (averageStatisticsGatheringTime > currentTimerDelay) {
currentTimerDelay *= 2;
}
@VisibleForTesting
- protected static long getCurrentTimerDelay() {
+ static long getCurrentTimerDelay() {
return currentTimerDelay;
}
final OutboundQueue queue = deviceContext.getPrimaryConnectionContext().getOutboundQueueProvider();
- final Long reserved = deviceContext.reservedXidForDeviceMessage();
+ final Long reserved = deviceContext.reserveXidForDeviceMessage();
final RequestContext<List<MultipartReply>> requestContext = new AbstractRequestContext<List<MultipartReply>>(
reserved) {
@Override
import io.netty.util.Timeout;
import java.math.BigInteger;
import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Assert;
import org.junit.Before;
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
MessageTranslator messageTranslatorFlowCapableNodeConnector;
@Mock
private MessageTranslator<Object, Object> messageTranslatorFlowRemoved;
+ @Mock
+ private LifecycleConductor lifecycleConductor;
private InOrder inOrderDevState;
org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved.class.getName()))))
.thenReturn(messageTranslatorFlowRemoved);
- deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, timer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false);
+ deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false);
xid = new Xid(atomicLong.incrementAndGet());
xidMulti = new Xid(atomicLong.incrementAndGet());
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullDataBroker() throws Exception {
- new DeviceContextImpl(connectionContext, deviceState, null, timer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
+ new DeviceContextImpl(connectionContext, deviceState, null, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
}
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullDeviceState() throws Exception {
- new DeviceContextImpl(connectionContext, null, dataBroker, timer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
+ new DeviceContextImpl(connectionContext, null, dataBroker, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
}
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullTimer() throws Exception {
- new DeviceContextImpl(null, deviceState, dataBroker, null, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
+ new DeviceContextImpl(null, deviceState, dataBroker, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
}
@Test
@Test
public void testGetReservedXid() {
- deviceContext.reservedXidForDeviceMessage();
+ deviceContext.reserveXidForDeviceMessage();
verify(outboundQueueProvider).reserveEntry();
}
assertEquals(translatorLibrary, pickedTranslatorLibrary);
}
- @Test
- public void testGetTimer() {
- final HashedWheelTimer pickedTimer = deviceContext.getTimer();
- assertEquals(timer, pickedTimer);
- }
-
@Test
public void testShutdownConnection() {
final ConnectionAdapter mockedConnectionAdapter = mock(ConnectionAdapter.class);
final ConnectionContext mockedAuxiliaryConnectionContext = prepareConnectionContext();
deviceContext.addAuxiliaryConnectionContext(mockedAuxiliaryConnectionContext);
final DeviceTerminationPhaseHandler mockedDeviceContextClosedHandler = mock(DeviceTerminationPhaseHandler.class);
- deviceContext.addDeviceContextClosedHandler(mockedDeviceContextClosedHandler);
when(deviceState.isValid()).thenReturn(true);
deviceContext.shutdownConnection();
verify(connectionContext).closeConnection(true);
@Test
public void testOnDeviceDisconnected() throws Exception {
final DeviceTerminationPhaseHandler deviceContextClosedHandler = mock(DeviceTerminationPhaseHandler.class);
- deviceContext.addDeviceContextClosedHandler(deviceContextClosedHandler);
// Mockito.verify(deviceState).setValid(false);
// Mockito.verify(deviceContextClosedHandler).onDeviceContextClosed(deviceContext);
import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.openflowplugin.impl.LifecycleConductorImpl;
import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
when(mockedWriteTransaction.submit()).thenReturn(mockedFuture);
final MessageIntelligenceAgency mockedMessageIntelligenceAgency = mock(MessageIntelligenceAgency.class);
- final DeviceManagerImpl deviceManager = new DeviceManagerImpl(mockedDataBroker, mockedMessageIntelligenceAgency,
- TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA, false, barrierIntervalNanos, barrierCountLimit);
+ final LifecycleConductor lifecycleConductor = new LifecycleConductorImpl(mockedMessageIntelligenceAgency);
+ final DeviceManagerImpl deviceManager = new DeviceManagerImpl(mockedDataBroker,
+ TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA, false, barrierIntervalNanos, barrierCountLimit, lifecycleConductor);
deviceManager.setDeviceInitializationPhaseHandler(deviceInitPhaseHandler);
deviceManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
final DeviceState mockedDeviceState = mock(DeviceState.class);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
when(mockedDeviceState.getRole()).thenReturn(OfpRole.BECOMEMASTER);
+ when(mockedDeviceState.getNodeId()).thenReturn(mockedNodeId);
if (withException) {
doThrow(new IllegalStateException("dummy")).when(mockedDeviceContext).initialSubmitTransaction();
}
-
- deviceManager.onDeviceContextLevelUp(mockedDeviceContext);
+ deviceManager.addDeviceContextToMap(mockedNodeId, mockedDeviceContext);
+ deviceManager.onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
if (withException) {
verify(mockedDeviceContext).close();
} else {
order.verify(mockConnectionContext).setOutboundQueueHandleRegistration(
Mockito.<OutboundQueueHandlerRegistration<OutboundQueueProvider>>any());
order.verify(mockConnectionContext).getNodeId();
- Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<DeviceContext>any());
+ Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<NodeId>any());
}
@Test
order.verify(mockConnectionContext).setOutboundQueueHandleRegistration(
Mockito.<OutboundQueueHandlerRegistration<OutboundQueueProvider>>any());
order.verify(mockConnectionContext).getNodeId();
- Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<DeviceContext>any());
+ Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<NodeId>any());
}
protected ConnectionContext buildMockConnectionContext(final short ofpVersion) {
*/
package org.opendaylight.openflowplugin.impl.role;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Matchers;
import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.mockito.stubbing.Answer;
import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutputBuilder;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Created by kramesha on 9/1/15.
+ * @author Jozef Bacigal
+ * Date: 4/19/16
+ * Time: 12:56
*/
@RunWith(MockitoJUnitRunner.class)
public class RoleContextImplTest {
- public static final int FUTURE_SAFETY_TIMEOUT = 5;
- @Mock
- private EntityOwnershipService entityOwnershipService;
-
- @Mock
- private DataBroker dataBroker;
-
- @Mock
- private RpcProviderRegistry rpcProviderRegistry;
-
- @Mock
- private DeviceContext deviceContext;
-
- @Mock
- private ConnectionContext connectionContext;
+ private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
@Mock
- private DeviceState deviceState;
+ private EntityOwnershipService entityOwnershipService;
@Mock
- private SalRoleService salRoleService;
+ private EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
@Mock
- private GetFeaturesOutput getFeaturesOutput;
-
- @Mock
- private FeaturesReply featuresReply;
- @Mock
- private MessageSpy mockedMessageSpy;
+ private LifecycleConductor conductor;
private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
- private final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier = DeviceStateUtil.createNodeInstanceIdentifier(nodeId);
private final Entity entity = new Entity(RoleManager.ENTITY_TYPE, nodeId.getValue());
private final Entity txEntity = new Entity(RoleManager.TX_ENTITY_TYPE, nodeId.getValue());
- private RoleContextImpl roleContext;
+ private RoleContext roleContext;
@Before
public void setup() throws CandidateAlreadyRegisteredException {
- when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
- when(deviceContext.getDeviceState()).thenReturn(deviceState);
- when(deviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
- when(connectionContext.getNodeId()).thenReturn(nodeId);
- when(deviceState.getNodeInstanceIdentifier()).thenReturn(instanceIdentifier);
- when(deviceState.getNodeId()).thenReturn(nodeId);
- when(rpcProviderRegistry.getRpcService(SalRoleService.class)).thenReturn(salRoleService);
- when(deviceState.getFeatures()).thenReturn(getFeaturesOutput);
- when(getFeaturesOutput.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
- when(deviceContext.getPrimaryConnectionContext().getFeatures()).thenReturn(featuresReply);
- when(deviceContext.getPrimaryConnectionContext().getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
- when(deviceContext.onClusterRoleChange(Matchers.<OfpRole>any(), Matchers.<OfpRole>any()))
- .thenReturn(Futures.immediateFuture((Void) null));
-
- roleContext = new RoleContextImpl(deviceContext, entityOwnershipService, entity, txEntity);
- roleContext.initializationRoleContext();
+ roleContext = new RoleContextImpl(nodeId, entityOwnershipService, entity, txEntity, conductor);
+ Mockito.when(entityOwnershipService.registerCandidate(entity)).thenReturn(entityOwnershipCandidateRegistration);
+ Mockito.when(entityOwnershipService.registerCandidate(txEntity)).thenReturn(entityOwnershipCandidateRegistration);
}
- @Test
- public void testOnRoleChangedStartingMaster() throws InterruptedException, ExecutionException, TimeoutException {
- final OfpRole oldRole = OfpRole.BECOMESLAVE;
- final OfpRole newRole = OfpRole.BECOMEMASTER;
+// @Test
+// Run this test only if demanded because it takes 15s to run
+ public void testInitializationThreads() throws Exception {
+
+ /*Setting answer which will hold the answer for 5s*/
+ Mockito.when(entityOwnershipService.registerCandidate(entity)).thenAnswer(new Answer<EntityOwnershipService>() {
+ @Override
+ public EntityOwnershipService answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ LOG.info("Sleeping this thread for 14s");
+ Thread.sleep(14000L);
+ return null;
+ }
+ });
- final SettableFuture<RpcResult<SetRoleOutput>> future = SettableFuture.create();
- future.set(RpcResultBuilder.<SetRoleOutput>success().build());
- when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
- .thenReturn(future);
+ Thread t1 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ LOG.info("Starting thread 1");
+ Assert.assertTrue(roleContext.initialization());
+ }
+ });
- roleContext.setSalRoleService(salRoleService);
+ Thread t2 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ LOG.info("Starting thread 2");
+ Assert.assertFalse(roleContext.initialization());
+ }
+ });
- final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
- onRoleChanged.get(FUTURE_SAFETY_TIMEOUT, TimeUnit.SECONDS);
+ t1.start();
+ LOG.info("Sleeping main thread for 1s to prevent race condition.");
+ Thread.sleep(1000L);
+ t2.start();
+
+ while (t2.isAlive()) {
+ //Waiting
+ }
- verify(deviceContext).onClusterRoleChange(oldRole, newRole);
}
@Test
- public void testOnRoleChangedStartingSlave() throws InterruptedException, ExecutionException, TimeoutException {
- final OfpRole oldRole = OfpRole.BECOMEMASTER;
- final OfpRole newRole = OfpRole.BECOMESLAVE;
-
- final SettableFuture<RpcResult<SetRoleOutput>> future = SettableFuture.create();
- future.set(RpcResultBuilder.<SetRoleOutput>success().build());
- when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
- .thenReturn(future);
-
- roleContext.setSalRoleService(salRoleService);
-
- final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
- onRoleChanged.get(5, TimeUnit.SECONDS);
-
- verify(deviceContext).onClusterRoleChange(oldRole, newRole);
+ public void testTermination() throws Exception {
+ roleContext.registerCandidate(entity);
+ roleContext.registerCandidate(txEntity);
+ Assert.assertTrue(roleContext.isMainCandidateRegistered());
+ Assert.assertTrue(roleContext.isTxCandidateRegistered());
+ roleContext.unregisterAllCandidates();
+ Assert.assertFalse(roleContext.isMainCandidateRegistered());
}
@Test
- public void testOnRoleChangedWorkingMaster() throws InterruptedException, ExecutionException, TimeoutException {
- final OfpRole oldRole = OfpRole.BECOMESLAVE;
- final OfpRole newRole = OfpRole.BECOMEMASTER;
-
- final ListenableFuture<RpcResult<SetRoleOutput>> future =
- RpcResultBuilder.success(new SetRoleOutputBuilder().build()).buildFuture();
- when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
- .thenReturn(future);
-
- roleContext.setSalRoleService(salRoleService);
+ public void testCreateRequestContext() throws Exception {
- final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
- onRoleChanged.get(5, TimeUnit.SECONDS);
+ }
- verify(deviceContext).onClusterRoleChange(oldRole, newRole);
+ @Test(expected = NullPointerException.class)
+ public void testSetSalRoleService() throws Exception {
+ roleContext.setSalRoleService(null);
}
@Test
- public void testOnRoleChangedWorkingSlave() throws InterruptedException, ExecutionException, TimeoutException {
- final OfpRole oldRole = OfpRole.BECOMEMASTER;
- final OfpRole newRole = OfpRole.BECOMESLAVE;
-
- final SettableFuture<RpcResult<SetRoleOutput>> future = SettableFuture.create();
- future.set(RpcResultBuilder.<SetRoleOutput>success().build());
- when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
- .thenReturn(future);
-
- roleContext.setSalRoleService(salRoleService);
-
- final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
- onRoleChanged.get(5, TimeUnit.SECONDS);
-
- verify(deviceContext).onClusterRoleChange(oldRole, newRole);
+ public void testGetEntity() throws Exception {
+ Assert.assertTrue(roleContext.getEntity().equals(entity));
}
- private class SetRoleInputMatcher extends ArgumentMatcher<SetRoleInput> {
-
- private final OfpRole ofpRole;
- private final NodeRef nodeRef;
-
- public SetRoleInputMatcher(final OfpRole ofpRole, final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier) {
- this.ofpRole = ofpRole;
- nodeRef = new NodeRef(instanceIdentifier);
+ @Test
+ public void testGetTxEntity() throws Exception {
+ Assert.assertTrue(roleContext.getTxEntity().equals(txEntity));
+ }
- }
+ @Test
+ public void testGetNodeId() throws Exception {
+ Assert.assertTrue(roleContext.getNodeId().equals(nodeId));
+ }
- @Override
- public boolean matches(final Object o) {
- final SetRoleInput input = (SetRoleInput) o;
- if (input.getControllerRole() == ofpRole &&
- input.getNode().equals(nodeRef)) {
- return true;
- }
- return false;
- }
+ @Test
+ public void testIsMaster() throws Exception {
+ Assert.assertTrue(roleContext.initialization());
+ Assert.assertFalse(roleContext.isMaster());
+ Assert.assertTrue(roleContext.registerCandidate(txEntity));
+ Assert.assertTrue(roleContext.isMaster());
+ Assert.assertTrue(roleContext.unregisterCandidate(entity));
+ Assert.assertFalse(roleContext.isMaster());
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.role;
+
+
+import java.math.BigInteger;
+
+import com.google.common.base.VerifyException;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+
+/**
+ * Created by Jozef Bacigal
+ * Date: 19.4.2016.
+ * Time: 13:08
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class RoleManagerImplTest {
+
+ @Mock
+ EntityOwnershipService entityOwnershipService;
+
+ @Mock
+ DataBroker dataBroker;
+
+ @Mock
+ DeviceContext deviceContext;
+
+ @Mock
+ DeviceManager deviceManager;
+
+ @Mock
+ EntityOwnershipListener entityOwnershipListener;
+
+ @Mock
+ EntityOwnershipListenerRegistration entityOwnershipListenerRegistration;
+
+ @Mock
+ EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
+
+ @Mock
+ ConnectionContext connectionContext;
+
+ @Mock
+ FeaturesReply featuresReply;
+
+ @Mock
+ DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
+
+ @Mock
+ DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
+
+ @Mock
+ WriteTransaction writeTransaction;
+
+ @Mock
+ LifecycleConductor conductor;
+
+ private RoleManagerImpl roleManager;
+ private RoleManagerImpl roleManagerSpy;
+ private RoleContext roleContextSpy;
+ private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
+
+ private final EntityOwnershipChange masterEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), false, true, true);
+ private final EntityOwnershipChange masterTxEntity = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), false, true, true);
+ private final EntityOwnershipChange slaveEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), true, false, true);
+ private final EntityOwnershipChange slaveTxEntityLast = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), true, false, false);
+
+ private InOrder inOrder;
+
+ @Before
+ public void setUp() throws Exception {
+ CheckedFuture<Void, TransactionCommitFailedException> future = Futures.immediateCheckedFuture(null);
+ Mockito.when(entityOwnershipService.registerListener(Mockito.anyString(), Mockito.any(EntityOwnershipListener.class))).thenReturn(entityOwnershipListenerRegistration);
+ Mockito.when(entityOwnershipService.registerCandidate(Mockito.any(Entity.class))).thenReturn(entityOwnershipCandidateRegistration);
+ Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
+ Mockito.when(connectionContext.getFeatures()).thenReturn(featuresReply);
+ Mockito.when(connectionContext.getNodeId()).thenReturn(nodeId);
+ Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
+ Mockito.when(featuresReply.getDatapathId()).thenReturn(new BigInteger("1"));
+ Mockito.when(featuresReply.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+ Mockito.doNothing().when(deviceInitializationPhaseHandler).onDeviceContextLevelUp(Mockito.<NodeId>any());
+ Mockito.doNothing().when(deviceTerminationPhaseHandler).onDeviceContextLevelDown(Mockito.<DeviceContext>any());
+ Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+ Mockito.when(writeTransaction.submit()).thenReturn(future);
+ Mockito.when(deviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(deviceContext);
+ roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker, conductor);
+ roleManager.setDeviceInitializationPhaseHandler(deviceInitializationPhaseHandler);
+ roleManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
+ Mockito.when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(deviceContext);
+ roleManagerSpy = Mockito.spy(roleManager);
+ Mockito.doNothing().when(roleManagerSpy).makeDeviceRoleChange(Mockito.<OfpRole>any(), Mockito.<RoleContext>any(), Mockito.anyBoolean());
+ roleManagerSpy.onDeviceContextLevelUp(nodeId);
+ roleContextSpy = Mockito.spy(roleManager.getRoleContext(nodeId));
+ inOrder = Mockito.inOrder(entityOwnershipListenerRegistration, roleManagerSpy, roleContextSpy);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test(expected = VerifyException.class)
+ public void testOnDeviceContextLevelUp() throws Exception {
+ roleManagerSpy.onDeviceContextLevelUp(nodeId);
+ inOrder.verify(roleManagerSpy).onDeviceContextLevelUp(nodeId);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testCloseMaster() throws Exception {
+ roleManagerSpy.ownershipChanged(masterEntity);
+ roleManagerSpy.ownershipChanged(masterTxEntity);
+ roleManagerSpy.close();
+ inOrder.verify(entityOwnershipListenerRegistration, Mockito.calls(2)).close();
+ inOrder.verify(roleManagerSpy).removeDeviceFromOperationalDS(nodeId);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testCloseSlave() throws Exception {
+ roleManagerSpy.ownershipChanged(slaveEntity);
+ roleManagerSpy.close();
+ inOrder.verify(entityOwnershipListenerRegistration, Mockito.calls(2)).close();
+ inOrder.verify(roleManagerSpy, Mockito.never()).removeDeviceFromOperationalDS(nodeId);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testOnDeviceContextLevelDown() throws Exception {
+ roleManagerSpy.onDeviceContextLevelDown(deviceContext);
+ inOrder.verify(roleManagerSpy).onDeviceContextLevelDown(deviceContext);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testOwnershipChanged1() throws Exception {
+ roleManagerSpy.ownershipChanged(masterEntity);
+ inOrder.verify(roleManagerSpy, Mockito.calls(1)).changeOwnershipForMainEntity(Mockito.<EntityOwnershipChange>any(),Mockito.<RoleContext>any());
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testOwnershipChanged2() throws Exception {
+ roleManagerSpy.ownershipChanged(masterEntity);
+ roleManagerSpy.ownershipChanged(masterTxEntity);
+ inOrder.verify(roleManagerSpy, Mockito.calls(1)).changeOwnershipForTxEntity(Mockito.<EntityOwnershipChange>any(),Mockito.<RoleContext>any());
+ inOrder.verify(roleManagerSpy, Mockito.calls(1)).makeDeviceRoleChange(Mockito.<OfpRole>any(), Mockito.<RoleContext>any(), Mockito.anyBoolean());
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testChangeOwnershipForMainEntity() throws Exception {
+ roleManagerSpy.changeOwnershipForMainEntity(masterEntity, roleContextSpy);
+ inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isMainCandidateRegistered();
+ inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).registerCandidate(Mockito.<Entity>any());
+ }
+
+ @Test
+ public void testChangeOwnershipForMainEntity2() throws Exception {
+ Mockito.when(roleContextSpy.isMainCandidateRegistered()).thenReturn(false);
+ roleManagerSpy.changeOwnershipForMainEntity(masterEntity, roleContextSpy);
+ inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isMainCandidateRegistered();
+ }
+
+ @Test
+ public void testChangeOwnershipForTxEntity() throws Exception {
+ Mockito.when(roleContextSpy.isTxCandidateRegistered()).thenReturn(true);
+ roleManagerSpy.changeOwnershipForTxEntity(slaveTxEntityLast, roleContextSpy);
+ inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isTxCandidateRegistered();
+ inOrder.verify(roleContextSpy, Mockito.calls(1)).unregisterCandidate(Mockito.<Entity>any());
+ inOrder.verify(roleContextSpy, Mockito.never()).close();
+ inOrder.verify(roleManagerSpy, Mockito.calls(1)).removeDeviceFromOperationalDS(Mockito.<NodeId>any());
+ }
+
+ @Test
+ public void testChangeOwnershipForTxEntity2() throws Exception {
+ roleManagerSpy.changeOwnershipForMainEntity(masterEntity, roleContextSpy);
+ roleManagerSpy.changeOwnershipForTxEntity(masterTxEntity, roleContextSpy);
+ inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isMainCandidateRegistered();
+ inOrder.verify(roleContextSpy, Mockito.calls(1)).registerCandidate(Mockito.<Entity>any());
+ inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isTxCandidateRegistered();
+ inOrder.verify(roleManagerSpy, Mockito.calls(1)).makeDeviceRoleChange(Mockito.<OfpRole>any(), Mockito.<RoleContext>any(), Mockito.anyBoolean());
+ }
+
+ @Test
+ public void testAddListener() throws Exception {
+ roleManager.addRoleChangeListener((new RoleChangeListener() {
+ @Override
+ public void roleInitializationDone(final NodeId nodeId, final boolean success) {
+ Assert.assertTrue(nodeId.equals(nodeId));
+ Assert.assertTrue(success);
+ }
+
+ @Override
+ public void roleChangeOnDevice(final NodeId nodeId_, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
+ Assert.assertTrue(nodeId.equals(nodeId_));
+ Assert.assertTrue(success);
+ Assert.assertFalse(initializationPhase);
+ Assert.assertTrue(newRole.equals(OfpRole.BECOMEMASTER));
+ }
+ }));
+ roleManager.notifyListenersRoleInitializationDone(nodeId, true);
+ roleManager.notifyListenersRoleChangeOnDevice(nodeId, true, OfpRole.BECOMEMASTER, false);
+ }
+
+
+}
\ No newline at end of file
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.XidSequencer;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
public class RpcContextImplTest {
@Mock
- private BindingAwareBroker.ProviderContext mockedRpcProviderRegistry;
+ private BindingAwareBroker.ProviderContext rpcProviderRegistry;
@Mock
private DeviceState deviceState;
@Mock
- private DeviceContext deviceContext;
+ private XidSequencer xidSequencer;
@Mock
private MessageSpy messageSpy;
- @Mock
- private NotificationPublishService notificationPublishService;
private KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
public void setup() {
final NodeId nodeId = new NodeId("openflow:1");
nodeInstanceIdentifier = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(nodeId));
-
- when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
- when(deviceContext.getDeviceState()).thenReturn(deviceState);
- }
-
- @Test
- public void invokeRpcTest() {
-
}
@Test
public void testStoreOrFail() throws Exception {
- try (final RpcContext rpcContext = new RpcContextImpl(messageSpy, mockedRpcProviderRegistry, deviceContext,
- 100, false, notificationPublishService)) {
+ try (final RpcContext rpcContext = new RpcContextImpl(rpcProviderRegistry, xidSequencer,
+ messageSpy, 100, nodeInstanceIdentifier)) {
final RequestContext<?> requestContext = rpcContext.createRequestContext();
assertNotNull(requestContext);
}
@Test
public void testStoreOrFailThatFails() throws Exception {
- try (final RpcContext rpcContext = new RpcContextImpl(messageSpy, mockedRpcProviderRegistry, deviceContext, 0,
- false, notificationPublishService)) {
+ try (final RpcContext rpcContext = new RpcContextImpl(rpcProviderRegistry, xidSequencer,
+ messageSpy, 0, nodeInstanceIdentifier)) {
final RequestContext<?> requestContext = rpcContext.createRequestContext();
assertNull(requestContext);
}
*/
package org.opendaylight.openflowplugin.impl.rpc;
-import static org.mockito.Mockito.times;
-
+import com.google.common.base.VerifyException;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+import org.opendaylight.openflowplugin.impl.LifecycleConductorImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@RunWith(MockitoJUnitRunner.class)
public class RpcManagerImplTest {
- private static final int AWAITED_NUM_OF_CALL_ADD_ROUTED_RPC = 12;
-
+ private static final int QUOTA_VALUE = 5;
private RpcManagerImpl rpcManager;
+
@Mock
private ProviderContext rpcProviderRegistry;
@Mock
@Mock
private DeviceInitializationPhaseHandler deviceINitializationPhaseHandler;
@Mock
- private ConnectionContext connectionContext;
- @Mock
- private BindingAwareBroker.RoutedRpcRegistration<RpcService> routedRpcRegistration;
- @Mock
private DeviceState deviceState;
@Mock
- private ItemLifeCycleRegistry itemLifeCycleRegistry;
+ private MessageSpy mockMsgSpy;
@Mock
- private MessageSpy messageSpy;
+ private LifecycleConductor conductor;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
private KeyedInstanceIdentifier<Node, NodeKey> nodePath;
+ private NodeId nodeId = new NodeId("openflow-junit:1");
+
@Before
public void setUp() {
- final NodeKey nodeKey = new NodeKey(new NodeId("openflow-junit:1"));
- nodePath = KeyedInstanceIdentifier.create(Nodes.class).child(Node.class, nodeKey);
- rpcManager = new RpcManagerImpl(rpcProviderRegistry, 5);
+ final NodeKey nodeKey = new NodeKey(nodeId);
+ rpcManager = new RpcManagerImpl(rpcProviderRegistry, QUOTA_VALUE, conductor);
rpcManager.setDeviceInitializationPhaseHandler(deviceINitializationPhaseHandler);
- FeaturesReply features = new GetFeaturesOutputBuilder()
- .setVersion(OFConstants.OFP_VERSION_1_3)
- .build();
- Mockito.when(connectionContext.getFeatures()).thenReturn(features);
- Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
- Mockito.when(deviceContext.getDeviceState().getRole()).thenReturn(OfpRole.BECOMEMASTER);
- Mockito.when(deviceContext.getItemLifeCycleSourceRegistry()).thenReturn(itemLifeCycleRegistry);
- Mockito.when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodePath);
- Mockito.when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
+ Mockito.when(deviceContext.getMessageSpy()).thenReturn(mockMsgSpy);
Mockito.when(deviceState.getNodeId()).thenReturn(nodeKey.getId());
+ Mockito.when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(deviceContext);
}
@Test
- public void testOnDeviceContextLevelUp() throws Exception {
-
- Mockito.when(rpcProviderRegistry.addRoutedRpcImplementation(
- Matchers.<Class<RpcService>>any(), Matchers.any(RpcService.class)))
- .thenReturn(routedRpcRegistration);
-
- rpcManager.onDeviceContextLevelUp(deviceContext);
+ public void onDeviceContextLevelUp() throws Exception {
+ rpcManager.onDeviceContextLevelUp(nodeId);
+ Mockito.verify(conductor).getDeviceContext(Mockito.<NodeId>any());
+ }
- Mockito.verify(rpcProviderRegistry, times(AWAITED_NUM_OF_CALL_ADD_ROUTED_RPC)).addRoutedRpcImplementation(
- Matchers.<Class<RpcService>>any(), Matchers.any(RpcService.class));
- Mockito.verify(routedRpcRegistration, times(AWAITED_NUM_OF_CALL_ADD_ROUTED_RPC)).registerPath(
- NodeContext.class, nodePath);
- Mockito.verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(deviceContext);
+ @Test
+ public void onDeviceContextLevelUpTwice() throws Exception {
+ rpcManager.onDeviceContextLevelUp(nodeId);
+ expectedException.expect(VerifyException.class);
+ rpcManager.onDeviceContextLevelUp(nodeId);
}
}
}
@Test
- public void testOnSuccessWithNotMultiNoMultipart() throws ExecutionException, InterruptedException {
+ public void testOnSuccessWithNotMultiNoMultipart() throws Exception {
final HelloMessage mockedHelloMessage = mock(HelloMessage.class);
multipartRequestOnTheFlyCallback.onSuccess(mockedHelloMessage);
* @throws InterruptedException
*/
@Test
- public void testOnSuccessWithValidMultipart1() throws ExecutionException, InterruptedException {
+ public void testOnSuccessWithValidMultipart1() throws Exception {
final MatchBuilder matchBuilder = new MatchBuilder()
.setMatchEntry(Collections.<MatchEntry>emptyList());
final FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder()
* @throws InterruptedException
*/
@Test
- public void testOnSuccessWithValidMultipart2() throws ExecutionException, InterruptedException {
+ public void testOnSuccessWithValidMultipart2() throws Exception {
final MultipartReplyMessageBuilder mpReplyMessage = new MultipartReplyMessageBuilder()
.setType(MultipartType.OFPMPDESC)
.setFlags(new MultipartRequestFlags(false));
when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
- when(mockedDeviceContext.getTimer()).thenReturn(mock(HashedWheelTimer.class));
when(mockedDeviceContext.getMultiMsgCollector(Matchers.<RequestContext<List<MultipartReply>>>any())).thenReturn(multiMessageCollector);
setup();
import static org.mockito.Mockito.when;
import org.junit.Before;
+import org.mockito.Mockito;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService;
import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-public class StatisticsContextImpMockInitiation {
- protected boolean isTable = false;
- protected boolean isFlow = false;
- protected boolean isGroup = false;
- protected boolean isMeter = false;
- protected boolean isPort = false;
- protected boolean isQueue = false;
+class StatisticsContextImpMockInitiation {
+ Boolean isTable = false;
+ Boolean isFlow = false;
+ Boolean isGroup = false;
+ Boolean isMeter = false;
+ Boolean isPort = false;
+ Boolean isQueue = false;
protected DeviceContext mockedDeviceContext;
- protected StatisticsGatheringService mockedStatisticsGatheringService;
- protected StatisticsGatheringOnTheFlyService mockedStatisticsOnFlyGatheringService;
- protected ConnectionContext mockedConnectionContext;
- protected FeaturesReply mockedFeatures;
+ StatisticsGatheringService mockedStatisticsGatheringService;
+ StatisticsGatheringOnTheFlyService mockedStatisticsOnFlyGatheringService;
+ ConnectionContext mockedConnectionContext;
protected DeviceState mockedDeviceState;
+ static final KeyedInstanceIdentifier<Node, NodeKey> dummyNodeII = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("dummyNodeId")));
protected MessageSpy mockedMessageSpy;
protected OutboundQueue mockedOutboundQueue;
-
- protected static final KeyedInstanceIdentifier<Node, NodeKey> dummyNodeII = InstanceIdentifier.create(Nodes.class)
- .child(Node.class, new NodeKey(new NodeId("dummyNodeId")));
+ protected DeviceManager mockedDeviceManager;
+ LifecycleConductor mockConductor;
@Before
public void initialize() {
mockedStatisticsGatheringService = mock(StatisticsGatheringService.class);
mockedStatisticsOnFlyGatheringService = mock(StatisticsGatheringOnTheFlyService.class);
mockedConnectionContext = mock(ConnectionContext.class);
- mockedFeatures = mock(FeaturesReply.class);
+ final FeaturesReply mockedFeatures = mock(FeaturesReply.class);
mockedDeviceState = mock(DeviceState.class);
- mockedMessageSpy = mock(MessageSpy.class);
- mockedOutboundQueue = mock(OutboundQueue.class);
+ final MessageSpy mockedMessageSpy = mock(MessageSpy.class);
+ final OutboundQueue mockedOutboundQueue = mock(OutboundQueue.class);
+ final DeviceManager mockedDeviceManager = mock(DeviceManager.class);
+ mockConductor = mock(LifecycleConductor.class);
+ when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+ when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
+ when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(isTable);
when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(isFlow);
when(mockedDeviceState.isGroupAvailable()).thenReturn(isGroup);
when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(isPort);
when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(isQueue);
when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
- when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
- when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
- when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
when(mockedConnectionContext.getNodeId()).thenReturn(dummyNodeII.getKey().getId());
when(mockedConnectionContext.getFeatures()).thenReturn(mockedFeatures);
when(mockedConnectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
when(mockedConnectionContext.getOutboundQueueProvider()).thenReturn(mockedOutboundQueue);
+ when(mockedDeviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+ mockConductor.setSafelyDeviceManager(mockedDeviceManager);
+ when(mockConductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.mockito.Mockito;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
import org.opendaylight.yangtools.yang.common.RpcResult;
@Test
public void gatherDynamicDataTest() {
- final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext, false);
+
+ final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
final ListenableFuture<RpcResult<List<MultipartReply>>> rpcResult = immediateFuture(RpcResultBuilder.success(Collections.<MultipartReply>emptyList()).build());
when(mockedStatisticsGatheringService.getStatisticsOfType(any(EventIdentifier.class), any(MultipartType
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
import org.opendaylight.yangtools.yang.common.RpcResult;
@Before
public void setUp() throws Exception {
- when(mockedDeviceContext.reservedXidForDeviceMessage()).thenReturn(TEST_XID);
+ when(mockedDeviceContext.reserveXidForDeviceMessage()).thenReturn(TEST_XID);
+ when(mockConductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
initStatisticsContext();
}
private void initStatisticsContext() {
- statisticsContext = new StatisticsContextImpl(mockedDeviceContext, false);
+ statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
statisticsContext.setStatisticsGatheringService(mockedStatisticsGatheringService);
statisticsContext.setStatisticsGatheringOnTheFlyService(mockedStatisticsOnFlyGatheringService);
}
*/
@Test
public void testClose() throws Exception {
- final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext, false);
+ final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
final RequestContext<Object> requestContext = statisticsContext.createRequestContext();
statisticsContext.close();
try {
@Test
public void testGatherDynamicData_all() throws Exception {
Mockito.reset(mockedDeviceState);
- when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(true);
- when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(true);
- when(mockedDeviceState.isGroupAvailable()).thenReturn(true);
- when(mockedDeviceState.isMetersAvailable()).thenReturn(true);
- when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(true);
- when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(true);
+ when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isGroupAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isMetersAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
initStatisticsContext();
}
@Test
- public void testWriteFlowStatistics() {
+ public void testWriteFlowStatistics() throws Exception {
final ArgumentCaptor<LogicalDatastoreType> dataStoreType = ArgumentCaptor.forClass(LogicalDatastoreType.class);
final ArgumentCaptor<InstanceIdentifier> flowPath = ArgumentCaptor.forClass(InstanceIdentifier.class);
final ArgumentCaptor<Flow> flow = ArgumentCaptor.forClass(Flow.class);
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
private ArgumentCaptor<ItemLifecycleListener> itemLifeCycleListenerCapt;
@Mock
private BindingAwareBroker.RpcRegistration<StatisticsManagerControlService> serviceControlRegistration;
+ @Mock
+ private DeviceManager deviceManager;
+ @Mock
+ private LifecycleConductor conductor;
private RequestContext<List<MultipartReply>> currentRequestContext;
private StatisticsManagerImpl statisticsManager;
when(mockedPrimConnectionContext.getNodeId()).thenReturn(new NodeId("ut-node:123"));
when(mockedPrimConnectionContext.getOutboundQueueProvider()).thenReturn(outboundQueue);
- when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(true);
- when(mockedDeviceState.isGroupAvailable()).thenReturn(true);
- when(mockedDeviceState.isMetersAvailable()).thenReturn(true);
- when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(true);
- when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(true);
- when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(true);
+ when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isGroupAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isMetersAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(Boolean.TRUE);
+ when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(Boolean.TRUE);
when(mockedDeviceState.getNodeId()).thenReturn(new NodeId("ofp-unit-dummy-node-id"));
when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
- when(mockedDeviceContext.getTimer()).thenReturn(hashedWheelTimer);
when(mockedDeviceContext.getMultiMsgCollector(
Matchers.<RequestContext<List<MultipartReply>>>any())).thenAnswer(
new Answer<MultiMsgCollector>() {
Matchers.eq(StatisticsManagerControlService.class),
Matchers.<StatisticsManagerControlService>any())).thenReturn(serviceControlRegistration);
- statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, false);
+ statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, false, conductor);
+ when(deviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+ when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
}
@Test
public void testOnDeviceContextLevelUp() throws Exception {
- Mockito.doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- final FutureCallback<OfHeader> callback = (FutureCallback<OfHeader>) invocation.getArguments()[2];
- LOG.debug("committing entry: {}", ((MultipartRequestInput) invocation.getArguments()[1]).getType());
- callback.onSuccess(null);
- currentRequestContext.setResult(RpcResultBuilder.<List<MultipartReply>>success().build());
- return null;
- }
- }).when(outboundQueue)
- .commitEntry(Matchers.anyLong(), Matchers.<OfHeader>any(), Matchers.<FutureCallback<OfHeader>>any());
-
- statisticsManager.setDeviceInitializationPhaseHandler(mockedDevicePhaseHandler);
- statisticsManager.onDeviceContextLevelUp(mockedDeviceContext);
-
- verify(mockedDeviceContext).addDeviceContextClosedHandler(statisticsManager);
- verify(mockedDeviceContext, Mockito.never()).reservedXidForDeviceMessage();
- verify(mockedDeviceState).setDeviceSynchronized(true);
- verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(mockedDeviceContext);
- verify(hashedWheelTimer).newTimeout(Matchers.<TimerTask>any(), Matchers.anyLong(), Matchers.<TimeUnit>any());
- }
-
- @Test
- public void testOnDeviceContextLevelUp1() throws Exception {
- statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, true);
+ statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, true, conductor);
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(final InvocationOnMock invocation) throws Throwable {
.commitEntry(Matchers.anyLong(), Matchers.<OfHeader>any(), Matchers.<FutureCallback<OfHeader>>any());
statisticsManager.setDeviceInitializationPhaseHandler(mockedDevicePhaseHandler);
- statisticsManager.onDeviceContextLevelUp(mockedDeviceContext);
+ statisticsManager.onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
- verify(mockedDeviceContext).addDeviceContextClosedHandler(statisticsManager);
- verify(mockedDeviceContext, Mockito.never()).reservedXidForDeviceMessage();
+ verify(mockedDeviceContext, Mockito.never()).reserveXidForDeviceMessage();
verify(mockedDeviceState).setDeviceSynchronized(true);
- verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(mockedDeviceContext);
+ verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
verify(hashedWheelTimer, Mockito.never()).newTimeout(Matchers.<TimerTask>any(), Matchers.anyLong(), Matchers.<TimeUnit>any());
}
new ChangeStatisticsWorkModeInputBuilder()
.setMode(StatisticsWorkMode.FULLYDISABLED);
- Future<RpcResult<Void>> workMode = statisticsManager
+ final Future<RpcResult<Void>> workMode = statisticsManager
.changeStatisticsWorkMode(changeStatisticsWorkModeInputBld.build());
checkWorkModeChangeOutcome(workMode);
*/
@Test
public void testChangeStatisticsWorkMode3() throws Exception {
- Timeout pollTimeout = Mockito.mock(Timeout.class);
- ItemLifeCycleSource itemLifecycleSource = Mockito.mock(ItemLifeCycleSource.class);
+ final Timeout pollTimeout = Mockito.mock(Timeout.class);
+ final ItemLifeCycleSource itemLifecycleSource = Mockito.mock(ItemLifeCycleSource.class);
Mockito.doNothing().when(itemLifecycleSource)
.setItemLifecycleListener(itemLifeCycleListenerCapt.capture());
@Test
public void testCalculateTimerDelay() throws Exception {
final TimeCounter timeCounter = Mockito.mock(TimeCounter.class);
- when(timeCounter.getAverageTimeBetweenMarks()).thenReturn(2000L, 4000L);
+ when(timeCounter.getAverageTimeBetweenMarks()).thenReturn((Long)2000L, (Long)4000L);
statisticsManager.calculateTimerDelay(timeCounter);
Assert.assertEquals(3000L, StatisticsManagerImpl.getCurrentTimerDelay());
when(mockFeatures.getDatapathId()).thenReturn(BigInteger.valueOf(21L));
}
@Test
- public void chainTableTrunkWriteOF10Test() {
- final DeviceState mockedDeviceState = mock(DeviceState.class);
+ public void chainTableTrunkWriteOF10Test() throws Exception {
+ DeviceState mockedDeviceState = mock(DeviceState.class);
final GetFeaturesOutput mockedFeatures = mock(GetFeaturesOutput.class);
when(mockedFeatures.getTables()).thenReturn((short) 2);
}
@Test
- public void testTranslateAndWriteReplyTypeDesc() {
+ public void testTranslateAndWriteReplyTypeDesc() throws Exception {
final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3);
Mockito.when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
final DeviceState deviceState = Mockito.mock(DeviceState.class);
}
@Test
- public void translateAndWriteReplyTypeTableFeatures() {
- final TableFeaturesBuilder tableFeature = new TableFeaturesBuilder();
+ public void translateAndWriteReplyTypeTableFeatures() throws Exception {
+ TableFeaturesBuilder tableFeature = new TableFeaturesBuilder();
tableFeature.setTableId(DUMMY_TABLE_ID);
final List<TableFeatures> tableFeatures = new ArrayList<>();
tableFeatures.add(tableFeature.build());
}
@Test
- public void translateAndWriteReplyTypeMeterFeatures() {
- final DeviceState mockedDeviceState = mock(DeviceState.class);
+ public void translateAndWriteReplyTypeMeterFeatures() throws Exception {
+ DeviceState mockedDeviceState = mock(DeviceState.class);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
final MultipartReplyMeterFeaturesBuilder multipartReplyMeterFeaturesBuilder = new MultipartReplyMeterFeaturesBuilder();
}
@Test
- public void translateAndWriteReplyTypeGroupFeatures() {
- final MultipartReplyGroupFeaturesBuilder multipartReplyGroupFeaturesBuilder = new MultipartReplyGroupFeaturesBuilder();
+ public void translateAndWriteReplyTypeGroupFeatures() throws Exception {
+ MultipartReplyGroupFeaturesBuilder multipartReplyGroupFeaturesBuilder = new MultipartReplyGroupFeaturesBuilder();
multipartReplyGroupFeaturesBuilder.setTypes(new GroupTypes(true, true, true, true));
multipartReplyGroupFeaturesBuilder.setCapabilities(new GroupCapabilities(true, true, true, true));
final ActionType actionType = new ActionType(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true);
@Test
- public void translateAndWriteReplyTypePortDesc() {
- final ConnectionContext mockedPrimaryConnectionContext = mock(ConnectionContext.class);
- final FeaturesReply mockedFeatures = mock(FeaturesReply.class);
+ public void translateAndWriteReplyTypePortDesc() throws Exception {
+ ConnectionContext mockedPrimaryConnectionContext = mock(ConnectionContext.class);
+ FeaturesReply mockedFeatures = mock(FeaturesReply.class);
when(mockedFeatures.getDatapathId()).thenReturn(new BigInteger(DUMMY_DATAPATH_ID));
when(mockedPrimaryConnectionContext.getFeatures()).thenReturn(mockedFeatures);
when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimaryConnectionContext);
}
@Test
- public void createSuccessProcessingCallbackTest() {
- final DeviceState mockedDeviceState = mock(DeviceState.class);
+ public void createSuccessProcessingCallbackTest() throws Exception {
+ DeviceState mockedDeviceState = mock(DeviceState.class);
when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3);
.put(OutputPortValues.ALL.toString(), Long.valueOf(PortNumberValuesV10.ALL.getIntValue())) //0xfffc
.put(OutputPortValues.CONTROLLER.toString(), Long.valueOf(PortNumberValuesV10.CONTROLLER.getIntValue())) //0xfffd
.put(OutputPortValues.LOCAL.toString(), Long.valueOf(PortNumberValuesV10.LOCAL.getIntValue())) //0xfffe
- .put(OutputPortValues.NONE.toString(), Long.valueOf(PortNumberValuesV10.NONE.getIntValue())) //0xfffe
+ .put(OutputPortValues.NONE.toString(), Long.valueOf(PortNumberValuesV10.NONE.getIntValue())) //0xffff
.build();
// openflow 1.3 reserved ports.
<properties>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
- <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
<openflowjava.version>0.8.0-SNAPSHOT</openflowjava.version>
<openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
<sal.api.version>0.11.0-SNAPSHOT</sal.api.version>