import io.netty.util.Timeout;
import java.math.BigInteger;
import java.util.List;
+import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.openflowplugin.api.openflow.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
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.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
/**
* The central entity of OFP is the Device Context, which encapsulate the logical state of a switch
AutoCloseable,
DeviceReplyProcessor,
TxFacade,
- DeviceRegistry{
+ DeviceRegistry,
+ RequestContextStack{
/**
* Method close all auxiliary connections and primary connection.
void replaceConnectionContext(ConnectionContext connectionContext);
boolean isSkipTableFeatures();
+
+ /**
+ * Setter for sal role service
+ * @param salRoleService
+ */
+ void setSalRoleService(@Nonnull final SalRoleService salRoleService);
+
+ /**
+ * Make device slave
+ * @return listenable future from sal role service
+ */
+ ListenableFuture<RpcResult<SetRoleOutput>> makeDeviceSlave();
}
package org.opendaylight.openflowplugin.api.openflow.device;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceConnectedHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
void setBarrierInterval(long barrierTimeoutLimit);
+ CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(DeviceInfo deviceInfo);
}
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterLifecycleSupervisor;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
*/
void setRpcContext(final RpcContext rpcContext);
- /**
- * Setter for role context
- * @param roleContext actual role context created per device
- */
- void setRoleContext(final RoleContext roleContext);
-
/**
* Setter for statistics context
* @param statContext actual statistics context created per device
+++ /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 com.google.common.util.concurrent.ListenableFuture;
-import javax.annotation.Nonnull;
-import org.opendaylight.openflowplugin.api.openflow.OFPContext;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-/**
- * Role context for change role on cluster
- */
-public interface RoleContext extends RequestContextStack, OFPContext {
-
- /**
- * Setter for sal role service
- * @param salRoleService
- */
- void setSalRoleService(@Nonnull final SalRoleService salRoleService);
-
- /**
- * Make device slave
- * @return listenable future from sal role service
- */
- ListenableFuture<RpcResult<SetRoleOutput>> makeDeviceSlave();
-}
+++ /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 com.google.common.util.concurrent.CheckedFuture;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-
-/**
- * Manager for role change on device
- */
-public interface RoleManager extends
- DeviceLifecycleSupervisor,
- DeviceInitializationPhaseHandler,
- AutoCloseable,
- DeviceTerminationPhaseHandler {
-
- CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final DeviceInfo deviceInfo);
-
-}
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.role.RoleManager;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterManager;
import org.opendaylight.openflowplugin.impl.connection.ConnectionManagerImpl;
import org.opendaylight.openflowplugin.impl.device.DeviceManagerImpl;
-import org.opendaylight.openflowplugin.impl.role.RoleManagerImpl;
import org.opendaylight.openflowplugin.impl.rpc.RpcManagerImpl;
import org.opendaylight.openflowplugin.impl.statistics.StatisticsManagerImpl;
import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyImpl;
private int barrierCountLimit;
private long echoReplyTimeout;
private DeviceManager deviceManager;
- private RoleManager roleManager;
private RpcManager rpcManager;
private RpcProviderRegistry rpcProviderRegistry;
private StatisticsManager statisticsManager;
((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota, extensionConverterManager, convertorManager, notificationPublishService);
- roleManager = new RoleManagerImpl(dataBroker, hashedWheelTimer);
statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOff, hashedWheelTimer, convertorManager);
/* Initialization Phase ordering - OFP Device Context suite */
connectionManager.setDeviceConnectedHandler(deviceManager);
deviceManager.setDeviceInitializationPhaseHandler(statisticsManager);
statisticsManager.setDeviceInitializationPhaseHandler(rpcManager);
- rpcManager.setDeviceInitializationPhaseHandler(roleManager);
- roleManager.setDeviceInitializationPhaseHandler(deviceManager);
+ rpcManager.setDeviceInitializationPhaseHandler(deviceManager);
/* Termination Phase ordering - OFP Device Context suite */
deviceManager.setDeviceTerminationPhaseHandler(rpcManager);
rpcManager.setDeviceTerminationPhaseHandler(statisticsManager);
- statisticsManager.setDeviceTerminationPhaseHandler(roleManager);
- roleManager.setDeviceTerminationPhaseHandler(deviceManager);
+ statisticsManager.setDeviceTerminationPhaseHandler(deviceManager);
rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
rpcManager.close();
statisticsManager.close();
- // TODO: needs to close org.opendaylight.openflowplugin.impl.role.OpenflowOwnershipListener after RoleContexts are down
- // TODO: must not be executed prior to all living RoleContexts have been closed (via closing living DeviceContexts)
- roleManager.close();
-
// Manually shutdown all remaining running threads in pool
threadPool.shutdown();
}
package org.opendaylight.openflowplugin.impl.device;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
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.HashedWheelTimer;
import io.netty.util.Timeout;
+import io.netty.util.TimerTask;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
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.NotificationPublishService;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
+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.DeviceInfo;
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.AbstractRequestContext;
import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtils;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
+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.SetRoleInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final float LOW_WATERMARK_FACTOR = 0.75f;
// TODO: high water mark factor should be parametrized
private static final float HIGH_WATERMARK_FACTOR = 0.95f;
+
+ // Timeout in seconds after what we will give up on propagating role
+ private static final int SET_ROLE_TIMEOUT = 10;
+
private boolean initialized;
+ private SalRoleService salRoleService = null;
+ private final HashedWheelTimer hashedWheelTimer;
private ConnectionContext primaryConnectionContext;
private final DeviceState deviceState;
private final DataBroker dataBroker;
private final ConvertorExecutor convertorExecutor;
private volatile CONTEXT_STATE state;
private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
+ private final DeviceManager myManager;
DeviceContextImpl(
@Nonnull final ConnectionContext primaryConnectionContext,
@Nonnull final TranslatorLibrary translatorLibrary,
@Nonnull final DeviceManager manager,
final ConvertorExecutor convertorExecutor,
- final boolean skipTableFeatures) {
+ final boolean skipTableFeatures,
+ final HashedWheelTimer hashedWheelTimer,
+ final DeviceManager myManager) {
this.primaryConnectionContext = primaryConnectionContext;
this.deviceInfo = primaryConnectionContext.getDeviceInfo();
+ this.hashedWheelTimer = hashedWheelTimer;
+ this.myManager = myManager;
this.deviceState = new DeviceStateImpl();
this.dataBroker = dataBroker;
this.auxiliaryConnectionContexts = new HashMap<>();
@Override
public ListenableFuture<Void> stopClusterServices(boolean deviceDisconnected) {
- return initialized
- ? this.transactionChainManager.deactivateTransactionManager()
- : Futures.immediateFuture(null);
+
+ ListenableFuture<Void> deactivateTxManagerFuture =
+ initialized ? transactionChainManager.deactivateTransactionManager() : Futures.immediateFuture(null);
+
+ if (!deviceDisconnected) {
+ ListenableFuture<Void> makeSlaveFuture = Futures.transform(makeDeviceSlave(), new Function<RpcResult<SetRoleOutput>, Void>() {
+ @Nullable
+ @Override
+ public Void apply(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
+ return null;
+ }
+ });
+
+ Futures.addCallback(makeSlaveFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(@Nullable Void aVoid) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Role SLAVE was successfully propagated on device, node {}", deviceInfo.getLOGValue());
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable throwable) {
+ LOG.warn("Was not able to set role SLAVE to device on node {} ", deviceInfo.getLOGValue());
+ LOG.trace("Error occurred on device role setting, probably connection loss: ", throwable);
+ myManager.removeDeviceFromOperationalDS(deviceInfo);
+ }
+ });
+
+ return Futures.transform(deactivateTxManagerFuture, new AsyncFunction<Void, Void>() {
+ @Override
+ public ListenableFuture<Void> apply(Void aVoid) throws Exception {
+ return makeSlaveFuture;
+ }
+ });
+ } else {
+ return Futures.transform(deactivateTxManagerFuture, new AsyncFunction<Void, Void>() {
+ @Override
+ public ListenableFuture<Void> apply(Void aVoid) throws Exception {
+ return myManager.removeDeviceFromOperationalDS(deviceInfo);
+ }
+ });
+ }
}
@Override
return this.skipTableFeatures;
}
+ @Override
+ public void setSalRoleService(@Nonnull SalRoleService salRoleService) {
+ this.salRoleService = salRoleService;
+ }
+
@Override
public void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler) {
this.clusterInitializationPhaseHandler = handler;
return false;
}
+ Futures.addCallback(sendRoleChangeToDevice(OfpRole.BECOMEMASTER), new RpcResultFutureCallback());
+
return this.clusterInitializationPhaseHandler.onContextInstantiateService(getPrimaryConnectionContext());
}
this.initialized = true;
}
}
+
+ @Nullable
+ @Override
+ public <T> RequestContext<T> createRequestContext() {
+ return new AbstractRequestContext<T>(deviceInfo.reserveXidForDeviceMessage()) {
+ @Override
+ public void close() {
+ }
+ };
+
+ }
+
+ ListenableFuture<RpcResult<SetRoleOutput>> sendRoleChangeToDevice(final OfpRole newRole) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Sending new role {} to device {}", newRole, deviceInfo.getNodeId());
+ }
+ final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
+ if (deviceInfo.getVersion() >= OFConstants.OFP_VERSION_1_3) {
+ final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
+ .setNode(new NodeRef(deviceInfo.getNodeInstanceIdentifier())).build();
+ setRoleOutputFuture = this.salRoleService.setRole(setRoleInput);
+ final TimerTask timerTask = timeout -> {
+ if (!setRoleOutputFuture.isDone()) {
+ LOG.warn("New role {} was not propagated to device {} during {} sec", newRole, deviceInfo.getLOGValue(), SET_ROLE_TIMEOUT);
+ setRoleOutputFuture.cancel(true);
+ }
+ };
+ hashedWheelTimer.newTimeout(timerTask, SET_ROLE_TIMEOUT, TimeUnit.SECONDS);
+ } else {
+ LOG.info("Device: {} with version: {} does not support role", deviceInfo.getLOGValue(), deviceInfo.getVersion());
+ return Futures.immediateFuture(null);
+ }
+ return JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<SetRoleOutput>> makeDeviceSlave() {
+ return sendRoleChangeToDevice(OfpRole.BECOMESLAVE);
+ }
+
+ private class RpcResultFutureCallback implements FutureCallback<RpcResult<SetRoleOutput>> {
+ @Override
+ public void onSuccess(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Role MASTER was successfully set on device, node {}", deviceInfo.getLOGValue());
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable throwable) {
+ LOG.warn("Was not able to set MASTER role on device, node {}", deviceInfo.getLOGValue());
+ shutdownConnection();
+ }
+ }
}
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
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.ListenableFuture;
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.NotificationPublishService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
import org.opendaylight.openflowplugin.impl.connection.OutboundQueueProviderImpl;
import org.opendaylight.openflowplugin.impl.device.listener.OpenflowProtocolListenerFullImpl;
import org.opendaylight.openflowplugin.impl.lifecycle.LifecycleServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.SalRoleServiceImpl;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
connectionAdapter.registerOutboundQueueHandler(outboundQueueProvider, barrierCountLimit, barrierIntervalNanos);
connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
+ final LifecycleService lifecycleService = new LifecycleServiceImpl();
+
final DeviceContext deviceContext = new DeviceContextImpl(
connectionContext,
dataBroker,
translatorLibrary,
this,
convertorExecutor,
- skipTableFeatures);
+ skipTableFeatures,
+ hashedWheelTimer,
+ this);
+ deviceContext.setSalRoleService(new SalRoleServiceImpl(deviceContext, deviceContext));
deviceContexts.put(deviceInfo, deviceContext);
- final LifecycleService lifecycleService = new LifecycleServiceImpl();
lifecycleService.setDeviceContext(deviceContext);
deviceContext.putLifecycleServiceIntoTxChainManager(lifecycleService);
lifecycleServices.put(deviceInfo, lifecycleService);
+ addCallbackToDeviceInitializeToSlave(deviceInfo, deviceContext, lifecycleService);
+
deviceContext.setSwitchFeaturesMandatory(switchFeaturesMandatory);
((ExtensionConverterProviderKeeper) deviceContext).setExtensionConverterProvider(extensionConverterProvider);
return ConnectionStatus.MAY_CONTINUE;
}
- private void updatePacketInRateLimiters() {
- synchronized (deviceContexts) {
- final int deviceContextsSize = deviceContexts.size();
- if (deviceContextsSize > 0) {
- long freshNotificationLimit = globalNotificationQuota / deviceContextsSize;
- if (freshNotificationLimit < 100) {
- freshNotificationLimit = 100;
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("fresh notification limit = {}", freshNotificationLimit);
- }
- for (final DeviceContext deviceContext : deviceContexts.values()) {
- deviceContext.updatePacketInRateLimit(freshNotificationLimit);
- }
- }
- }
- }
-
@Override
public TranslatorLibrary oook() {
return translatorLibrary;
this.barrierIntervalNanos = TimeUnit.MILLISECONDS.toNanos(barrierTimeoutLimit);
}
+ @Override
+ public CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final DeviceInfo deviceInfo) {
+ final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
+ delWtx.delete(LogicalDatastoreType.OPERATIONAL, deviceInfo.getNodeInstanceIdentifier());
+ final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
+
+ Futures.addCallback(delFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Delete Node {} was successful", deviceInfo.getLOGValue());
+ }
+ }
+
+ @Override
+ public void onFailure(@Nonnull final Throwable t) {
+ LOG.warn("Delete node {} failed with exception {}", deviceInfo.getLOGValue(), t);
+ }
+ });
+
+ return delFuture;
+ }
+
+
+ private void addCallbackToDeviceInitializeToSlave(final DeviceInfo deviceInfo, final DeviceContext deviceContext, final LifecycleService lifecycleService) {
+ Futures.addCallback(deviceContext.makeDeviceSlave(), new FutureCallback<RpcResult<SetRoleOutput>>() {
+ @Override
+ public void onSuccess(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Role SLAVE was successfully propagated on device, node {}", deviceInfo.getLOGValue());
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.warn("Was not able to set role SLAVE to device on node {} ",deviceInfo.getLOGValue());
+ lifecycleService.closeConnection();
+ }
+ });
+ }
+
+ private void updatePacketInRateLimiters() {
+ synchronized (deviceContexts) {
+ final int deviceContextsSize = deviceContexts.size();
+ if (deviceContextsSize > 0) {
+ long freshNotificationLimit = globalNotificationQuota / deviceContextsSize;
+ if (freshNotificationLimit < 100) {
+ freshNotificationLimit = 100;
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("fresh notification limit = {}", freshNotificationLimit);
+ }
+ for (final DeviceContext deviceContext : deviceContexts.values()) {
+ deviceContext.updatePacketInRateLimit(freshNotificationLimit);
+ }
+ }
+ }
+ }
+
+ @VisibleForTesting
+ void setDeviceContext(final DeviceInfo deviceInfo, final DeviceContext deviceContext) {
+ this.deviceContexts.putIfAbsent(deviceInfo, deviceContext);
+ }
+
+ @VisibleForTesting
+ int getDeviceContextCount() {
+ return this.deviceContexts.size();
+ }
+
+
}
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
private boolean inClosing = false;
private DeviceContext deviceContext;
private RpcContext rpcContext;
- private RoleContext roleContext;
private StatisticsContext statContext;
private ClusterSingletonServiceRegistration registration;
private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
// Chain all jobs that will stop our services
final List<ListenableFuture<Void>> futureList = new ArrayList<>();
- futureList.add(roleContext.stopClusterServices(connectionInterrupted));
futureList.add(statContext.stopClusterServices(connectionInterrupted));
futureList.add(rpcContext.stopClusterServices(connectionInterrupted));
futureList.add(deviceContext.stopClusterServices(connectionInterrupted));
this.clusterInitializationPhaseHandler = deviceContext;
this.deviceContext.setLifecycleInitializationPhaseHandler(this.statContext);
this.statContext.setLifecycleInitializationPhaseHandler(this.rpcContext);
- this.rpcContext.setLifecycleInitializationPhaseHandler(this.roleContext);
- this.roleContext.setLifecycleInitializationPhaseHandler(this);
+ this.rpcContext.setLifecycleInitializationPhaseHandler(this);
//Set initial submit handler
this.statContext.setInitialSubmitHandler(this.deviceContext);
//Register cluster singleton service
this.rpcContext = rpcContext;
}
- @Override
- public void setRoleContext(final RoleContext roleContext) {
- this.roleContext = roleContext;
- }
-
@Override
public void setStatContext(final StatisticsContext statContext) {
this.statContext = statContext;
+++ /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.impl.role;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-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.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.TimerTask;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
-import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
-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.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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Role context try to make change device role on device
- */
-class RoleContextImpl implements RoleContext {
-
- private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
-
- // Timeout in seconds after what we will give up on propagating role
- private static final int SET_ROLE_TIMEOUT = 10;
-
- private SalRoleService salRoleService = null;
- private final HashedWheelTimer hashedWheelTimer;
- private final DeviceInfo deviceInfo;
- private CONTEXT_STATE state;
- private final RoleManager myManager;
- private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
- private final LifecycleService lifecycleService;
-
- RoleContextImpl(final DeviceInfo deviceInfo,
- final HashedWheelTimer hashedWheelTimer,
- final RoleManager myManager,
- final LifecycleService lifecycleService) {
- this.deviceInfo = deviceInfo;
- this.state = CONTEXT_STATE.WORKING;
- this.myManager = myManager;
- this.hashedWheelTimer = hashedWheelTimer;
- this.lifecycleService = lifecycleService;
- }
-
- @Nullable
- @Override
- public <T> RequestContext<T> createRequestContext() {
- return new AbstractRequestContext<T>(deviceInfo.reserveXidForDeviceMessage()) {
- @Override
- public void close() {
- }
- };
- }
-
- @Override
- public void setSalRoleService(@Nonnull final SalRoleService salRoleService) {
- Preconditions.checkNotNull(salRoleService);
- this.salRoleService = salRoleService;
- }
-
- @Override
- public CONTEXT_STATE getState() {
- return this.state;
- }
-
- @Override
- public void setState(CONTEXT_STATE state) {
- this.state = state;
- }
-
- @Override
- public ServiceGroupIdentifier getServiceIdentifier() {
- return this.deviceInfo.getServiceIdentifier();
- }
-
- @Override
- public DeviceInfo getDeviceInfo() {
- return this.deviceInfo;
- }
-
- public void startupClusterServices() throws ExecutionException, InterruptedException {
- Futures.addCallback(sendRoleChangeToDevice(OfpRole.BECOMEMASTER), new RpcResultFutureCallback());
- }
-
- @Override
- public ListenableFuture<Void> stopClusterServices(final boolean deviceDisconnected) {
-
- if (!deviceDisconnected) {
- ListenableFuture<Void> future = Futures.transform(makeDeviceSlave(), new Function<RpcResult<SetRoleOutput>, Void>() {
- @Nullable
- @Override
- public Void apply(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
- return null;
- }
- });
-
- Futures.addCallback(future, new FutureCallback<Void>() {
- @Override
- public void onSuccess(@Nullable Void aVoid) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Role SLAVE was successfully propagated on device, node {}", deviceInfo.getLOGValue());
- }
- }
-
- @Override
- public void onFailure(final Throwable throwable) {
- LOG.warn("Was not able to set role SLAVE to device on node {} ", deviceInfo.getLOGValue());
- LOG.trace("Error occurred on device role setting, probably connection loss: ", throwable);
- myManager.removeDeviceFromOperationalDS(deviceInfo);
- }
- });
- return future;
- } else {
- return myManager.removeDeviceFromOperationalDS(deviceInfo);
- }
- }
-
- @Override
- public ListenableFuture<RpcResult<SetRoleOutput>> makeDeviceSlave(){
- return sendRoleChangeToDevice(OfpRole.BECOMESLAVE);
- }
-
- @VisibleForTesting
- ListenableFuture<RpcResult<SetRoleOutput>> sendRoleChangeToDevice(final OfpRole newRole) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Sending new role {} to device {}", newRole, deviceInfo.getNodeId());
- }
- final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
- if (deviceInfo.getVersion() >= OFConstants.OFP_VERSION_1_3) {
- final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
- .setNode(new NodeRef(deviceInfo.getNodeInstanceIdentifier())).build();
- setRoleOutputFuture = this.salRoleService.setRole(setRoleInput);
- final TimerTask timerTask = timeout -> {
- if (!setRoleOutputFuture.isDone()) {
- LOG.warn("New role {} was not propagated to device {} during {} sec", newRole, deviceInfo.getLOGValue(), SET_ROLE_TIMEOUT);
- setRoleOutputFuture.cancel(true);
- }
- };
- hashedWheelTimer.newTimeout(timerTask, SET_ROLE_TIMEOUT, TimeUnit.SECONDS);
- } else {
- LOG.info("Device: {} with version: {} does not support role", deviceInfo.getLOGValue(), deviceInfo.getVersion());
- return Futures.immediateFuture(null);
- }
- return JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture);
- }
-
- @Override
- public void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler) {
- this.clusterInitializationPhaseHandler = handler;
- }
-
- @Override
- public boolean onContextInstantiateService(final ConnectionContext connectionContext) {
-
- if (connectionContext.getConnectionState().equals(ConnectionContext.CONNECTION_STATE.RIP)) {
- LOG.warn("Connection on device {} was interrupted, will stop starting master services.", deviceInfo.getLOGValue());
- return false;
- }
-
- Futures.addCallback(sendRoleChangeToDevice(OfpRole.BECOMEMASTER), new RpcResultFutureCallback());
- return this.clusterInitializationPhaseHandler.onContextInstantiateService(connectionContext);
- }
-
- private class RpcResultFutureCallback implements FutureCallback<RpcResult<SetRoleOutput>> {
- @Override
- public void onSuccess(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Role MASTER was successfully set on device, node {}", deviceInfo.getLOGValue());
- }
- }
-
- @Override
- public void onFailure(final Throwable throwable) {
- LOG.warn("Was not able to set MASTER role on device, node {}", deviceInfo.getLOGValue());
- lifecycleService.closeConnection();
- }
- }
-}
+++ /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.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 io.netty.util.HashedWheelTimer;
-import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-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.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-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.LifecycleService;
-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.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 SalRoleService.
- *
- * Hands over to StatisticsManager at the end.
- */
-public class RoleManagerImpl implements RoleManager {
- private static final Logger LOG = LoggerFactory.getLogger(RoleManagerImpl.class);
-
- // Maximum limit of timeout retries when cleaning DS, to prevent infinite recursive loops
- private static final int MAX_CLEAN_DS_RETRIES = 3;
-
- private DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
- private DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
- private final DataBroker dataBroker;
- private final ConcurrentMap<DeviceInfo, RoleContext> contexts = new ConcurrentHashMap<>();
- private final HashedWheelTimer hashedWheelTimer;
-
- public RoleManagerImpl(final DataBroker dataBroker, final HashedWheelTimer hashedWheelTimer) {
- this.dataBroker = Preconditions.checkNotNull(dataBroker);
- this.hashedWheelTimer = hashedWheelTimer;
- }
-
- @Override
- public void setDeviceInitializationPhaseHandler(final DeviceInitializationPhaseHandler handler) {
- deviceInitializationPhaseHandler = handler;
- }
-
- @Override
- public void onDeviceContextLevelUp(@CheckForNull final DeviceInfo deviceInfo, final LifecycleService lifecycleService) throws Exception {
- final DeviceContext deviceContext = Preconditions.checkNotNull(lifecycleService.getDeviceContext());
- final RoleContext roleContext = new RoleContextImpl(deviceInfo, hashedWheelTimer, this, lifecycleService);
- roleContext.setSalRoleService(new SalRoleServiceImpl(roleContext, deviceContext));
- Verify.verify(contexts.putIfAbsent(deviceInfo, roleContext) == null, "Role context for master Node %s is still not closed.", deviceInfo.getLOGValue());
- Futures.addCallback(roleContext.makeDeviceSlave(), new FutureCallback<RpcResult<SetRoleOutput>>() {
- @Override
- public void onSuccess(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Role SLAVE was successfully propagated on device, node {}", deviceInfo.getLOGValue());
- }
- }
-
- @Override
- public void onFailure(Throwable throwable) {
- LOG.warn("Was not able to set role SLAVE to device on node {} ",deviceInfo.getLOGValue());
- lifecycleService.closeConnection();
- }
- });
- lifecycleService.setRoleContext(roleContext);
- deviceInitializationPhaseHandler.onDeviceContextLevelUp(deviceInfo, lifecycleService);
- }
-
- @Override
- public void close() {
- LOG.debug("Close method on role manager was called.");
- 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 roleContext = iterator.next();
- contexts.remove(roleContext.getDeviceInfo());
- removeDeviceFromOperationalDS(roleContext.getDeviceInfo());
- }
- }
-
- @Override
- public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
- contexts.remove(deviceInfo);
- deviceTerminationPhaseHandler.onDeviceContextLevelDown(deviceInfo);
- }
-
- @Override
- public CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final DeviceInfo deviceInfo) {
- final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
- delWtx.delete(LogicalDatastoreType.OPERATIONAL, deviceInfo.getNodeInstanceIdentifier());
- final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
-
- Futures.addCallback(delFuture, new FutureCallback<Void>() {
- @Override
- public void onSuccess(final Void result) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Delete Node {} was successful", deviceInfo.getLOGValue());
- }
- }
-
- @Override
- public void onFailure(@Nonnull final Throwable t) {
- LOG.warn("Delete node {} failed with exception {}", deviceInfo.getLOGValue(), t);
- }
- });
-
- return delFuture;
- }
-
- @Override
- public void setDeviceTerminationPhaseHandler(final DeviceTerminationPhaseHandler handler) {
- deviceTerminationPhaseHandler = handler;
- }
-
- @VisibleForTesting
- RoleContext getRoleContext(final DeviceInfo deviceInfo){
- return contexts.get(deviceInfo);
- }
-
-}
translatorLibrary,
deviceManager,
convertorExecutor,
- false);
+ false, timer, deviceManager);
deviceContextSpy = Mockito.spy(deviceContext);
xid = new Xid(atomicLong.incrementAndGet());
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullDataBroker() throws Exception {
- new DeviceContextImpl(connectionContext, null, null, translatorLibrary, deviceManager, convertorExecutor,false).close();
+ new DeviceContextImpl(connectionContext, null, null, translatorLibrary, deviceManager, convertorExecutor,false, timer, deviceManager).close();
}
@Test(expected = NullPointerException.class)
public void testDeviceContextImplConstructorNullTimer() throws Exception {
- new DeviceContextImpl(null, dataBroker, null, translatorLibrary, deviceManager,convertorExecutor,false).close();
+ new DeviceContextImpl(null, dataBroker, null, translatorLibrary, deviceManager,convertorExecutor,false, timer, deviceManager).close();
}
@Test
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
+import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
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.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.CapabilitiesV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPortBuilder;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
@RunWith(MockitoJUnitRunner.class)
public class DeviceManagerImplTest {
private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
@Mock
private ConvertorExecutor convertorExecutor;
-
+ @Mock
+ private KeyedInstanceIdentifier<Node, NodeKey> key;
@Before
public void setUp() throws Exception {
OpenflowPortsUtil.init();
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
@Mock
private RpcContext rpcContext;
@Mock
- private RoleContext roleContext;
- @Mock
private StatisticsContext statContext;
@Mock
private ConnectionContext connectionContext;
Mockito.when(deviceInfo.getLOGValue()).thenReturn(TEST_NODE);
Mockito.when(deviceContext.stopClusterServices(Mockito.anyBoolean())).thenReturn(Futures.immediateFuture(null));
- Mockito.when(roleContext.stopClusterServices(Mockito.anyBoolean())).thenReturn(Futures.immediateFuture(null));
Mockito.when(statContext.stopClusterServices(Mockito.anyBoolean())).thenReturn(Futures.immediateFuture(null));
Mockito.when(rpcContext.stopClusterServices(Mockito.anyBoolean())).thenReturn(Futures.immediateFuture(null));
lifecycleService = new LifecycleServiceImpl();
lifecycleService.setDeviceContext(deviceContext);
lifecycleService.setRpcContext(rpcContext);
- lifecycleService.setRoleContext(roleContext);
lifecycleService.setStatContext(statContext);
lifecycleService.registerService(clusterSingletonServiceProvider);
}
Mockito.verify(statContext).setLifecycleInitializationPhaseHandler(Mockito.any());
Mockito.verify(statContext).setInitialSubmitHandler(Mockito.any());
Mockito.verify(rpcContext).setLifecycleInitializationPhaseHandler(Mockito.any());
- Mockito.verify(roleContext).setLifecycleInitializationPhaseHandler(Mockito.any());
}
@Test
Mockito.verify(statContext).stopClusterServices(false);
Mockito.verify(deviceContext).stopClusterServices(false);
Mockito.verify(rpcContext).stopClusterServices(false);
- Mockito.verify(roleContext).stopClusterServices(false);
}
@Test
+++ /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.impl.role;
-
-
-import com.google.common.util.concurrent.Futures;
-import io.netty.util.HashedWheelTimer;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
-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.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;
-
-@RunWith(MockitoJUnitRunner.class)
-public class RoleContextImplTest {
-
- @Mock
- HashedWheelTimer hashedWheelTimer;
- @Mock
- private DeviceInfo deviceInfo;
- @Mock
- private RoleManager roleManager;
- @Mock
- private LifecycleService lifecycleService;
- @Mock
- private SalRoleService salRoleService;
-
- private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
- private RoleContext roleContext;
- private RoleContextImpl roleContextSpy;
-
- @Before
- public void setup() throws CandidateAlreadyRegisteredException {
- roleContext = new RoleContextImpl(deviceInfo, hashedWheelTimer, roleManager, lifecycleService);
- roleContext.setSalRoleService(salRoleService);
- Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
- Mockito.when(salRoleService.setRole(Mockito.<SetRoleInput>any())).thenReturn(Futures.immediateFuture(null));
- Mockito.when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(DeviceStateUtil.createNodeInstanceIdentifier(nodeId));
- roleContextSpy = Mockito.spy((RoleContextImpl) roleContext);
- }
-
- @Test
- public void testCreateRequestContext() throws Exception {
- roleContext.createRequestContext();
- Mockito.verify(deviceInfo).reserveXidForDeviceMessage();
- }
-
- @Test(expected = NullPointerException.class)
- public void testSetSalRoleService() throws Exception {
- roleContext.setSalRoleService(null);
- }
-
- @Test
- public void testGetNodeId() throws Exception {
- Assert.assertTrue(roleContext.getDeviceInfo().getNodeId().equals(nodeId));
- }
-
- @Test
- public void startupClusterServices() throws Exception {
- roleContextSpy.startupClusterServices();
- Mockito.verify(roleContextSpy).sendRoleChangeToDevice(OfpRole.BECOMEMASTER);
- }
-
- @Test
- public void startupClusterServicesVersion10() throws Exception {
- Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
- roleContextSpy.startupClusterServices();
- Mockito.verify(roleContextSpy).sendRoleChangeToDevice(OfpRole.BECOMEMASTER);
- }
-
- @Test
- public void startupClusterServicesVersion13() throws Exception {
- Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- roleContextSpy.startupClusterServices();
- Mockito.verify(roleContextSpy).sendRoleChangeToDevice(OfpRole.BECOMEMASTER);
- }
-
- @Test
- public void stopClusterServicesNotDisconnected() throws Exception {
- roleContextSpy.stopClusterServices(false);
- Mockito.verify(roleContextSpy).sendRoleChangeToDevice(OfpRole.BECOMESLAVE);
- Mockito.verify(roleManager, Mockito.never()).removeDeviceFromOperationalDS(Mockito.<DeviceInfo>any());
- }
-
- @Test
- public void stopClusterServicesDisconnected() throws Exception {
- roleContextSpy.stopClusterServices(true);
- Mockito.verify(roleManager, Mockito.atLeastOnce()).removeDeviceFromOperationalDS(Mockito.<DeviceInfo>any());
- }
-
- @Test
- public void makeDeviceSlave() throws Exception {
- roleContextSpy.makeDeviceSlave();
- Mockito.verify(roleContextSpy).sendRoleChangeToDevice(OfpRole.BECOMESLAVE);
- }
-
-}
+++ /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 static org.mockito.Mockito.verify;
-
-import com.google.common.base.VerifyException;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
-import io.netty.util.HashedWheelTimer;
-import java.math.BigInteger;
-import org.junit.After;
-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.data.TransactionCommitFailedException;
-import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
-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.DeviceInfo;
-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.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
-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.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.yangtools.yang.binding.KeyedInstanceIdentifier;
-
-@RunWith(MockitoJUnitRunner.class)
-public class RoleManagerImplTest {
-
- @Mock
- DataBroker dataBroker;
- @Mock
- DeviceContext deviceContext;
- @Mock
- DeviceManager deviceManager;
- @Mock
- ConnectionContext connectionContext;
- @Mock
- FeaturesReply featuresReply;
- @Mock
- DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
- @Mock
- DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
- @Mock
- WriteTransaction writeTransaction;
- @Mock
- DeviceState deviceState;
- @Mock
- DeviceInfo deviceInfo;
- @Mock
- DeviceInfo deviceInfo2;
- @Mock
- MessageSpy messageSpy;
- @Mock
- OutboundQueue outboundQueue;
- @Mock
- GetFeaturesOutput featuresOutput;
- @Mock
- LifecycleService lifecycleService;
-
- private RoleManagerImpl roleManager;
- private RoleManagerImpl roleManagerSpy;
- private RoleContext roleContextSpy;
- private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
- private final NodeId nodeId2 = NodeId.getDefaultInstance("openflow:2");
-
- private InOrder inOrder;
-
- @Before
- public void setUp() throws Exception {
- CheckedFuture<Void, TransactionCommitFailedException> future = Futures.immediateCheckedFuture(null);
- Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
- Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
- Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
- Mockito.when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
- Mockito.when(deviceContext.getPrimaryConnectionContext().getOutboundQueueProvider()).thenReturn(outboundQueue);
- Mockito.when(connectionContext.getFeatures()).thenReturn(featuresReply);
- Mockito.when(connectionContext.getNodeId()).thenReturn(nodeId);
- Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
- Mockito.when(deviceInfo.getDatapathId()).thenReturn(new BigInteger("1"));
- Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
- Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
- Mockito.doNothing().when(deviceInitializationPhaseHandler).onDeviceContextLevelUp(Mockito.<DeviceInfo>any(), Mockito.<LifecycleService>any());
- Mockito.doNothing().when(deviceTerminationPhaseHandler).onDeviceContextLevelDown(Mockito.<DeviceInfo>any());
- Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
- Mockito.when(writeTransaction.submit()).thenReturn(future);
- Mockito.when(deviceInfo.getNodeId()).thenReturn(nodeId);
- Mockito.when(deviceInfo2.getNodeId()).thenReturn(nodeId2);
- Mockito.when(deviceInfo.getDatapathId()).thenReturn(BigInteger.TEN);
- Mockito.when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(DeviceStateUtil.createNodeInstanceIdentifier(nodeId));
- Mockito.when(lifecycleService.getDeviceContext()).thenReturn(deviceContext);
- roleManager = new RoleManagerImpl(dataBroker, new HashedWheelTimer());
- roleManager.setDeviceInitializationPhaseHandler(deviceInitializationPhaseHandler);
- roleManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
- roleManagerSpy = Mockito.spy(roleManager);
- roleManagerSpy.onDeviceContextLevelUp(deviceInfo, lifecycleService);
- roleContextSpy = Mockito.spy(roleManager.getRoleContext(deviceInfo));
- Mockito.when(roleContextSpy.getDeviceInfo()).thenReturn(deviceInfo);
- Mockito.when(roleContextSpy.getDeviceInfo().getNodeId()).thenReturn(nodeId);
- inOrder = Mockito.inOrder(roleManagerSpy, roleContextSpy);
- }
-
- @After
- public void tearDown() throws Exception {
- }
-
- @Test(expected = VerifyException.class)
- public void testOnDeviceContextLevelUp() throws Exception {
- roleManagerSpy.onDeviceContextLevelUp(deviceInfo, lifecycleService);
- inOrder.verify(roleManagerSpy).onDeviceContextLevelUp(deviceInfo, lifecycleService);
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testCloseMaster() throws Exception {
- roleManagerSpy.close();
- inOrder.verify(roleManagerSpy).removeDeviceFromOperationalDS(Mockito.eq(deviceInfo));
- inOrder.verifyNoMoreInteractions();
- }
-
- @Test
- public void testOnDeviceContextLevelDown() throws Exception {
- roleManagerSpy.onDeviceContextLevelDown(deviceInfo);
- inOrder.verify(roleManagerSpy).onDeviceContextLevelDown(deviceInfo);
- inOrder.verifyNoMoreInteractions();
- }
-}
\ No newline at end of file