import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterLifecycleSupervisor;
/**
* General API for all OFP Context
*/
-public interface OFPContext {
+public interface OFPContext extends ClusterLifecycleSupervisor, ClusterInitializationPhaseHandler {
void setState(CONTEXT_STATE contextState);
*/
CONTEXT_STATE getState();
- /**
- * Starting cluster services for context becoming master
- */
- default void startupClusterServices() throws ExecutionException, InterruptedException {
- throw new InterruptedException("Cannot start abstract service, check implementation of cluster services");
- }
-
/**
* About to stop services in cluster not master anymore or going down
* @return Future most of services need time to be closed
- * @param deviceDisconnected
+ * @param deviceDisconnected true if clustering services stopping by device disconnect
*/
default ListenableFuture<Void> stopClusterServices(final boolean deviceDisconnected){
return Futures.immediateFailedFuture(new RejectedExecutionException("Cannot stop abstract services, check implementation of cluster services"));
+++ /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;
-
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-
-/**
- * Generic API for all managers
- */
-public interface OFPManager {
-
- <T extends OFPContext> T gainContext(final DeviceInfo deviceInfo);
-
-}
package org.opendaylight.openflowplugin.api.openflow.device;
-import org.opendaylight.openflowplugin.api.openflow.OFPManager;
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;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
import org.opendaylight.openflowplugin.api.openflow.translator.TranslatorLibrarian;
/**
* has its own device context managed by this manager.
*/
public interface DeviceManager extends DeviceConnectedHandler, DeviceDisconnectedHandler, DeviceLifecycleSupervisor,
- DeviceInitializationPhaseHandler, DeviceTerminationPhaseHandler, TranslatorLibrarian, AutoCloseable, OFPManager {
+ DeviceInitializationPhaseHandler, DeviceTerminationPhaseHandler, TranslatorLibrarian, AutoCloseable {
/**
--- /dev/null
+/**
+ * Copyright (c) 2016 Pantheon Technologies s.r.o. 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.handlers;
+
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+
+/**
+ * Interface handles MASTER initialization on ownership change
+ */
+public interface ClusterInitializationPhaseHandler {
+
+ /**
+ * Method for initialization cycle between contexts
+ * @param connectionContext to check actual connection state
+ */
+ boolean onContextInstantiateService(final ConnectionContext connectionContext);
+
+ /**
+ * Method for initial submit transaction after successful initial gathering
+ */
+ default void initialSubmitTransaction(){
+ //This method need to be override only in device context to submit initial data
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2016 Pantheon Technologies s.r.o. 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.handlers;
+
+/**
+ * Interface has to implement all relevant manager to correctly handling
+ * device context initialization when device MASTER. Methods are used for order
+ * handlers in initialization phase. Ordering is easily changed
+ * pragmatically by definition.
+ */
+public interface ClusterLifecycleSupervisor {
+
+ /**
+ * Method sets relevant {@link ClusterInitializationPhaseHandler} for building
+ * handler's chain for Device mastership phase.
+ * @param handler handler
+ */
+ void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler);
+
+ default void setInitialSubmitHandler(final ClusterInitializationPhaseHandler initialSubmitHandler) {
+ //Need to be only set in statistics context where after successful initial gather
+ //tx need to be submitted
+ }
+
+}
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
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;
/**
* Service for starting or stopping all services in plugin in cluster
*/
-public interface LifecycleService extends ClusterSingletonService, AutoCloseable {
+public interface LifecycleService extends ClusterSingletonService, AutoCloseable, ClusterLifecycleSupervisor, ClusterInitializationPhaseHandler {
/**
* This method registers lifecycle service to the given provider
import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.openflowplugin.api.openflow.OFPManager;
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;
DeviceLifecycleSupervisor,
DeviceInitializationPhaseHandler,
AutoCloseable,
- DeviceTerminationPhaseHandler,
- OFPManager {
+ DeviceTerminationPhaseHandler {
CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final DeviceInfo deviceInfo, final int numRetries);
}
package org.opendaylight.openflowplugin.api.openflow.rpc;
-import org.opendaylight.openflowplugin.api.openflow.OFPManager;
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;
* The RPC Manager will maintain an RPC Context for each online switch. RPC context for device is created when
* {@link DeviceInitializationPhaseHandler#onDeviceContextLevelUp(DeviceInfo, org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService)}
* is called.
- * <p>
- * Created by Martin Bobak <mbobak@cisco.com> on 25.2.2015.
*/
-public interface RpcManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable, DeviceTerminationPhaseHandler, OFPManager {
+public interface RpcManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable, DeviceTerminationPhaseHandler {
void setStatisticsRpcEnabled(boolean statisticsRpcEnabled);
}
import io.netty.util.Timeout;
import java.util.Optional;
import org.opendaylight.openflowplugin.api.openflow.OFPContext;
-import org.opendaylight.openflowplugin.api.openflow.OFPManager;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
package org.opendaylight.openflowplugin.api.openflow.statistics;
-import org.opendaylight.openflowplugin.api.openflow.OFPManager;
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;
* Manager to start or stop scheduling statistics
*/
public interface StatisticsManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler,
- DeviceTerminationPhaseHandler, AutoCloseable, OFPManager {
+ DeviceTerminationPhaseHandler, AutoCloseable {
/**
* Start scheduling statistic gathering for given device info
LOG.debug("succeeded by getting sweep barrier after post-handshake for device {}", connectionContext.getNodeId().getValue());
try {
ConnectionStatus connectionStatusResult = deviceConnectedHandler.deviceConnected(connectionContext);
- if (ConnectionStatus.CLOSING.equals(connectionStatusResult)) {
- connectionContext.closeConnection(false);
+ if (!ConnectionStatus.MAY_CONTINUE.equals(connectionStatusResult)) {
+ connectionContext.closeConnection(ConnectionStatus.ALREADY_CONNECTED.equals(connectionStatusResult));
}
SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
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.ClusterInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
private final DeviceInfo deviceInfo;
private final ConvertorExecutor convertorExecutor;
private volatile CONTEXT_STATE state;
+ private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
public DeviceContextImpl(
@Nonnull final ConnectionContext primaryConnectionContext,
this.state = state;
}
- @Override
- public void startupClusterServices() throws ExecutionException, InterruptedException {
- LOG.debug("Initializing transaction chain manager for node {}", getDeviceInfo().getLOGValue());
- this.transactionChainManager.activateTransactionManager();
- LOG.debug("Waiting to get node {} information", getDeviceInfo().getLOGValue());
- DeviceInitializationUtils.initializeNodeInformation(this, switchFeaturesMandatory, this.convertorExecutor);
- }
-
@Override
public ListenableFuture<Void> stopClusterServices(boolean deviceDisconnected) {
return this.transactionChainManager.deactivateTransactionManager();
public boolean isSkipTableFeatures() {
return this.skipTableFeatures;
}
+
+ @Override
+ public void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler) {
+ this.clusterInitializationPhaseHandler = handler;
+ }
+
+ @Override
+ public boolean onContextInstantiateService(final ConnectionContext connectionContext) {
+
+ if (getPrimaryConnectionContext().getConnectionState().equals(ConnectionContext.CONNECTION_STATE.RIP)) {
+ LOG.warn("Connection on device {} was interrupted, will stop starting master services.", deviceInfo.getLOGValue());
+ return false;
+ }
+
+ LOG.info("Starting device context cluster services for node {}", deviceInfo.getLOGValue());
+
+ this.transactionChainManager.activateTransactionManager();
+
+ try {
+ DeviceInitializationUtils.initializeNodeInformation(this, switchFeaturesMandatory, this.convertorExecutor);
+ } catch (ExecutionException | InterruptedException e) {
+ LOG.warn("Device {} cannot be initialized: ", deviceInfo.getLOGValue(), e);
+ return false;
+ }
+
+ return this.clusterInitializationPhaseHandler.onContextInstantiateService(getPrimaryConnectionContext());
+ }
}
*/
if (deviceContexts.containsKey(deviceInfo)) {
DeviceContext deviceContext = deviceContexts.get(deviceInfo);
+ LOG.warn("Node {} already connected disconnecting device. Rejecting connection", deviceInfo);
if (!deviceContext.getState().equals(OFPContext.CONTEXT_STATE.TERMINATION)) {
- LOG.info("Node {} already connected but context state not in TERMINATION state, replacing connection context",
+ LOG.warn("Node {} context state not in TERMINATION state.",
connectionContext.getDeviceInfo().getLOGValue());
- deviceContext.replaceConnectionContext(connectionContext);
return ConnectionStatus.ALREADY_CONNECTED;
} else {
- LOG.warn("Rejecting connection from node which is already connected and there exist deviceContext for it: {}",
- connectionContext.getDeviceInfo().getLOGValue());
return ConnectionStatus.CLOSING;
}
}
deviceContexts.put(deviceInfo, deviceContext);
}
- @Override
- public <T extends OFPContext> T gainContext(final DeviceInfo deviceInfo) {
- return (T) deviceContexts.get(deviceInfo);
- }
-
@Override
public void setIsNotificationFlowRemovedOff(boolean isNotificationFlowRemovedOff) {
this.isNotificationFlowRemovedOff = isNotificationFlowRemovedOff;
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+/**
+ * Copyright (c) 2016 Pantheon Technologies s.r.o. 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,
import java.util.Collection;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
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;
private RoleContext roleContext;
private StatisticsContext statContext;
private ClusterSingletonServiceRegistration registration;
+ private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
@Override
public void instantiateServiceInstance() {
- try {
- if (LOG.isDebugEnabled()) {
- LOG.debug("========== Starting clustering MASTER services for node {} ==========", this.deviceContext.getDeviceInfo().getLOGValue());
- }
-
- if (connectionInterrupted()) {
- return;
- }
-
- LOG.info("Starting device context cluster services for node {}", getIdentifier());
- this.deviceContext.startupClusterServices();
-
- if (connectionInterrupted()) {
- return;
- }
-
- LOG.info("Starting statistics context cluster services for node {}", getIdentifier());
- this.statContext.startupClusterServices();
-
- if (connectionInterrupted()) {
- return;
- }
-
- LOG.info("Statistics initial gathering OK, submitting data for node {}", getIdentifier());
- this.deviceContext.initialSubmitTransaction();
-
- if (connectionInterrupted()) {
- return;
- }
-
- LOG.info("Starting rpc context cluster services for node {}", getIdentifier());
- this.rpcContext.startupClusterServices();
-
- if (connectionInterrupted()) {
- return;
- }
+ LOG.info("========== Starting clustering MASTER services for node {} ==========", this.deviceContext.getDeviceInfo().getLOGValue());
- LOG.info("Starting role context cluster services for node {}", getIdentifier());
- this.roleContext.startupClusterServices();
-
- if (connectionInterrupted()) {
- return;
- }
-
- LOG.info("Caching flows IDs ...");
- fillDeviceFlowRegistry();
-
- } catch (ExecutionException | InterruptedException e) {
- LOG.warn("Cluster service {} was unable to start.", this.getIdentifier());
- this.deviceContext.shutdownConnection();
+ if (this.clusterInitializationPhaseHandler.onContextInstantiateService(null)) {
+ LOG.info("========== Start-up clustering MASTER services for node {} was SUCCESSFUL ==========", this.deviceContext.getDeviceInfo().getLOGValue());
+ } else {
+ LOG.warn("========== Start-up clustering MASTER services for node {} was UN-SUCCESSFUL ==========", this.deviceContext.getDeviceInfo().getLOGValue());
+ this.closeConnection();
}
- }
- private boolean connectionInterrupted() {
- if (this.deviceContext.getPrimaryConnectionContext().getConnectionState().equals(ConnectionContext.CONNECTION_STATE.RIP)) {
- LOG.warn("Node {} was disconnected, will stop starting MASTER services.", this.deviceContext.getDeviceInfo().getLOGValue());
- return true;
- }
- return false;
}
@Override
@Override
public void registerService(final ClusterSingletonServiceProvider singletonServiceProvider) {
+ //lifecycle service -> device context -> statistics context -> rpc context -> role context -> lifecycle service
+ this.clusterInitializationPhaseHandler = deviceContext;
+ this.deviceContext.setLifecycleInitializationPhaseHandler(this.statContext);
+ this.statContext.setLifecycleInitializationPhaseHandler(this.rpcContext);
+ this.rpcContext.setLifecycleInitializationPhaseHandler(this.roleContext);
+ this.roleContext.setLifecycleInitializationPhaseHandler(this);
+ //Set initial submit handler
+ this.statContext.setInitialSubmitHandler(this.deviceContext);
+ //Register cluster singleton service
this.registration = singletonServiceProvider.registerClusterSingletonService(this);
}
});
}
+ @Override
+ public void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler) {
+ this.clusterInitializationPhaseHandler = handler;
+ }
+
+ @Override
+ public boolean onContextInstantiateService(final ConnectionContext connectionContext) {
+
+ if (ConnectionContext.CONNECTION_STATE.RIP.equals(connectionContext.getConnectionState())) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Connection to the device {} was interrupted.", this.deviceContext.getDeviceInfo().getLOGValue());
+ }
+ return false;
+ }
+
+ LOG.info("Caching flows IDs ...");
+ fillDeviceFlowRegistry();
+ return true;
+ }
}
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.role.RoleContext;
import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
private final DeviceInfo deviceInfo;
private CONTEXT_STATE state;
private final RoleManager myManager;
+ private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
RoleContextImpl(final DeviceInfo deviceInfo,
final HashedWheelTimer hashedWheelTimer,
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 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());
+ }
+ });
+
+ return this.clusterInitializationPhaseHandler.onContextInstantiateService(connectionContext);
+ }
}
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.OFPContext;
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;
return contexts.get(deviceInfo);
}
- @Override
- public <T extends OFPContext> T gainContext(final DeviceInfo deviceInfo) {
- return (T) contexts.get(deviceInfo);
- }
}
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Semaphore;
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.mdsal.singleton.common.api.ServiceGroupIdentifier;
+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.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
private final ExtensionConverterProvider extensionConverterProvider;
private final ConvertorExecutor convertorExecutor;
private final NotificationPublishService notificationPublishService;
+ private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
RpcContextImpl(final DeviceInfo deviceInfo,
final RpcProviderRegistry rpcProviderRegistry,
}
@Override
- public void startupClusterServices() throws ExecutionException, InterruptedException {
+ public ListenableFuture<Void> stopClusterServices(boolean deviceDisconnected) {
+ MdSalRegistrationUtils.unregisterServices(this);
+ return Futures.immediateFuture(null);
+ }
+
+ @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;
+ }
+
MdSalRegistrationUtils.registerServices(this, deviceContext, extensionConverterProvider, convertorExecutor);
if (isStatisticsRpcEnabled) {
MdSalRegistrationUtils.registerStatCompatibilityServices(
notificationPublishService,
convertorExecutor);
}
-
- }
-
- @Override
- public ListenableFuture<Void> stopClusterServices(boolean deviceDisconnected) {
- MdSalRegistrationUtils.unregisterServices(this);
- return Futures.immediateFuture(null);
+ return this.clusterInitializationPhaseHandler.onContextInstantiateService(connectionContext);
}
}
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.openflowplugin.api.openflow.OFPContext;
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;
}
}
- @Override
- public <T extends OFPContext> T gainContext(DeviceInfo deviceInfo) {
- return (T) contexts.get(deviceInfo);
- }
-
@Override
public void setStatisticsRpcEnabled(boolean statisticsRpcEnabled) {
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
-import java.util.concurrent.ExecutionException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
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.rpc.listener.ItemLifecycleListener;
import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
private volatile boolean schedulingEnabled;
private volatile CONTEXT_STATE state;
+ private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
+ private ClusterInitializationPhaseHandler initialSubmitHandler;
StatisticsContextImpl(@Nonnull final DeviceInfo deviceInfo,
final boolean shuttingDownStatisticsPolling,
return this.deviceInfo;
}
- @Override
- public void startupClusterServices() throws ExecutionException, InterruptedException {
- if (!this.shuttingDownStatisticsPolling) {
- this.statListForCollectingInitialization();
- this.initialGatherDynamicData();
- myManager.startScheduling(deviceInfo);
- }
- }
-
@Override
public ListenableFuture<Void> stopClusterServices(boolean deviceDisconnected) {
myManager.stopScheduling(deviceInfo);
public LifecycleService getLifecycleService() {
return lifecycleService;
}
+
+ @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;
+ }
+
+ if (!this.shuttingDownStatisticsPolling) {
+
+ LOG.info("Starting statistics context cluster services for node {}", deviceInfo.getLOGValue());
+
+ this.statListForCollectingInitialization();
+ Futures.addCallback(this.initialGatherDynamicData(), new FutureCallback<Boolean>() {
+
+ @Override
+ public void onSuccess(@Nullable Boolean aBoolean) {
+ initialSubmitHandler.initialSubmitTransaction();
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.warn("Initial gathering statistics unsuccessful for node {}", deviceInfo.getLOGValue());
+ lifecycleService.closeConnection();
+ }
+ });
+
+ myManager.startScheduling(deviceInfo);
+
+ }
+
+ return this.clusterInitializationPhaseHandler.onContextInstantiateService(connectionContext);
+ }
+
+ @Override
+ public void setInitialSubmitHandler(final ClusterInitializationPhaseHandler initialSubmitHandler) {
+ this.initialSubmitHandler = initialSubmitHandler;
+ }
}
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.OFPContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
this.deviceTerminPhaseHandler = handler;
}
- @Override
- public <T extends OFPContext> T gainContext(DeviceInfo deviceInfo) {
- return (T) contexts.get(deviceInfo);
- }
}
/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2016 Pantheon Technologies s.r.o. 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,
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.handlers.ClusterInitializationPhaseHandler;
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;
lifecycleService.setRpcContext(rpcContext);
lifecycleService.setRoleContext(roleContext);
lifecycleService.setStatContext(statContext);
+ lifecycleService.registerService(clusterSingletonServiceProvider);
Mockito.when(deviceContext.getDeviceInfo()).thenReturn(deviceInfo);
Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
Mockito.when(deviceContext.getDeviceFlowRegistry()).thenReturn(deviceFlowRegistry);
@Test
public void instantiateServiceInstance() throws Exception {
lifecycleService.instantiateServiceInstance();
- Mockito.verify(deviceContext).startupClusterServices();
- Mockito.verify(statContext).startupClusterServices();
- Mockito.verify(deviceContext).initialSubmitTransaction();
- Mockito.verify(rpcContext).startupClusterServices();
- Mockito.verify(roleContext).startupClusterServices();
+ Mockito.verify(deviceContext).setLifecycleInitializationPhaseHandler(Mockito.<ClusterInitializationPhaseHandler>any());
+ Mockito.verify(statContext).setLifecycleInitializationPhaseHandler(Mockito.<ClusterInitializationPhaseHandler>any());
+ Mockito.verify(statContext).setInitialSubmitHandler(Mockito.<ClusterInitializationPhaseHandler>any());
+ Mockito.verify(rpcContext).setLifecycleInitializationPhaseHandler(Mockito.<ClusterInitializationPhaseHandler>any());
+ Mockito.verify(roleContext).setLifecycleInitializationPhaseHandler(Mockito.<ClusterInitializationPhaseHandler>any());
}
@Test