Bug 5596 Initial commit failed 85/43585/6
authorJozef Bacigal <jozef.bacigal@pantheon.tech>
Wed, 10 Aug 2016 08:25:08 +0000 (10:25 +0200)
committerJozef Bacigal <jozef.bacigal@pantheon.tech>
Mon, 15 Aug 2016 08:51:51 +0000 (08:51 +0000)
- added closing connection after unsuccessful initial submit
- added enum with possible connection state after handshake

Change-Id: I62e06f8189dc593bc40267c96d253fdfe53b3a20
Signed-off-by: Jozef Bacigal <jozef.bacigal@pantheon.tech>
17 files changed:
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionStatus.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceInfo.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/handlers/DeviceConnectedHandler.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/RoleChangeListener.java [deleted file]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleManager.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/LifecycleServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImpl.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java

diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionStatus.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionStatus.java
new file mode 100644 (file)
index 0000000..09e7823
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * 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.connection;
+
+/**
+ * Define all possible states of connection after handshake
+ */
+public enum ConnectionStatus {
+
+    // this flag should be return if no connection on this node exists
+    MAY_CONTINUE,
+
+    // this flag should be return if node still connected but not in termination state
+    ALREADY_CONNECTED,
+
+    // this flag should be return if node still connected but already in termination state
+    CLOSING
+}
index d69dc9f5b4c566fb358b05ba9f102851c0dd69b4..8114ff0dbcff7f57352650bfe3e3304c5cfdd9b4 100644 (file)
@@ -17,6 +17,7 @@ import org.opendaylight.openflowplugin.api.openflow.OFPContext;
 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.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 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;
@@ -133,5 +134,8 @@ public interface DeviceContext extends
 
     void setSwitchFeaturesMandatory(boolean switchFeaturesMandatory);
 
+    void putLifecycleServiceIntoTxChainManager(LifecycleService lifecycleService);
+
+    void replaceConnectionContext(ConnectionContext connectionContext);
 }
 
index fa4a212cd8f34ecb750a82f83cb99ced1167ed1b..ca94ad152c8621077cabf1ddd8e7a589f9d5e5a9 100644 (file)
@@ -45,4 +45,12 @@ public interface DeviceInfo extends XidSequencer {
      */
     ServiceGroupIdentifier getServiceIdentifier();
 
+    /**
+     * Many uses in log, this will make code more readable
+     * @return string representation of nodeId
+     */
+    default String getLOGValue() {
+        return getNodeId().getValue();
+    }
+
 }
index 8900357eb5f0e03503ccfa5fb6c009e80f38366b..1587f7762789b64b626f56717994505c70ebda8b 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.openflowplugin.api.openflow.device.handlers;
 
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionStatus;
 
 /**
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 26.2.2015.
@@ -19,6 +20,6 @@ public interface DeviceConnectedHandler {
      * Method is used to propagate information about established connection with device.
      * It propagates connected device's connection context.
      */
-    boolean deviceConnected(ConnectionContext connectionContext) throws Exception;
+    ConnectionStatus deviceConnected(ConnectionContext connectionContext) throws Exception;
 
 }
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/RoleChangeListener.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/RoleChangeListener.java
deleted file mode 100644 (file)
index 64a72fa..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.openflowplugin.api.openflow.device.DeviceInfo;
-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 deviceInfo
-     * @param success or failure
-     */
-    void roleInitializationDone(final DeviceInfo deviceInfo, final boolean success);
-
-    /**
-     * Notification when the role change on device is done
-     * @param deviceInfo
-     * @param newRole
-     */
-    void roleChangeOnDevice(final DeviceInfo deviceInfo, final OfpRole newRole);
-
-}
index 923853fd639827d0a21feb49abd148a20304745b..e14631a414a69f3cea9e3c0b71fdfda5f3749cfc 100644 (file)
@@ -14,7 +14,6 @@ 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;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
 
 /**
  * Manager for role change on device
index dea0a5e6818b424021bc293bdb6635e1c706301b..30eccf1db3b0049e81f8774239b20144ee598eab 100644 (file)
@@ -129,8 +129,8 @@ public class ConnectionContextImpl implements ConnectionContext {
             future.get(1, TimeUnit.SECONDS);
             LOG.info("Unregister outbound queue successful.");
         } catch (InterruptedException | TimeoutException | ExecutionException e) {
-            LOG.warn("Unregister outbound queue throws exception for node {} ", nodeId);
-            LOG.trace("Unregister outbound queue throws exception for node {} ", nodeId, e);
+            LOG.warn("Unregister outbound queue throws exception for node {} ", getSafeNodeIdForLOG());
+            LOG.trace("Unregister outbound queue throws exception for node {} ", getSafeNodeIdForLOG(), e);
         }
 
         closeHandshakeContext();
@@ -140,15 +140,15 @@ public class ConnectionContextImpl implements ConnectionContext {
         }
 
         if (propagate) {
-            LOG.debug("Propagating device disconnect for node {}", nodeId);
+            LOG.debug("Propagating device disconnect for node {}", getSafeNodeIdForLOG());
             propagateDeviceDisconnectedEvent();
         } else {
-            LOG.debug("Close connection without propagating for node {}", nodeId);
+            LOG.debug("Close connection without propagating for node {}", getSafeNodeIdForLOG());
         }
     }
 
     private void closeHandshakeContext() {
-        LOG.debug("Trying closing handshake context for node {}", nodeId);
+        LOG.debug("Trying closing handshake context for node {}", getSafeNodeIdForLOG());
         if (handshakeContext != null) {
             try {
                 handshakeContext.close();
@@ -196,6 +196,14 @@ public class ConnectionContextImpl implements ConnectionContext {
         }
     }
 
+    /**
+     * This method returns safe nodeId for logging
+     * @return string value od nodeId or string "null"
+     */
+    private String getSafeNodeIdForLOG() {
+        return null == nodeId ? "null" : nodeId.getValue();
+    }
+
     @Override
     public void setOutboundQueueHandleRegistration(OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration) {
         this.outboundQueueHandlerRegistration = outboundQueueHandlerRegistration;
index 8bbe07bfaf92aef2bdcb67aabcfcb90606a5bb79..d1de6f8a20305ada3620e476394c9e08e186990d 100644 (file)
@@ -14,6 +14,7 @@ import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ListenableFuture;
 import javax.annotation.Nullable;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionStatus;
 import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceConnectedHandler;
 import org.opendaylight.openflowplugin.api.openflow.md.core.HandshakeListener;
@@ -65,15 +66,16 @@ public class HandshakeListenerImpl implements HandshakeListener {
         return new FutureCallback<RpcResult<BarrierOutput>>() {
             @Override
             public void onSuccess(@Nullable final RpcResult<BarrierOutput> result) {
-                LOG.debug("succeeded by getting sweep barrier after posthandshake for device {}", connectionContext.getNodeId());
+                LOG.debug("succeeded by getting sweep barrier after post-handshake for device {}", connectionContext.getNodeId().getValue());
                 try {
-                    if (!deviceConnectedHandler.deviceConnected(connectionContext)) {
-                        connectionContext.closeConnection(true);
+                    ConnectionStatus connectionStatusResult = deviceConnectedHandler.deviceConnected(connectionContext);
+                    if (ConnectionStatus.CLOSING.equals(connectionStatusResult)) {
+                        connectionContext.closeConnection(false);
                     }
                     SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
                             SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
                 } catch (final Exception e) {
-                    LOG.error("ConnectionContext initial processing failed: {}", e.getMessage());
+                    LOG.error("ConnectionContext initial processing failed: ", e);
                     SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
                             SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
                     connectionContext.closeConnection(true);
@@ -82,7 +84,7 @@ public class HandshakeListenerImpl implements HandshakeListener {
 
             @Override
             public void onFailure(final Throwable t) {
-                LOG.error("failed to get sweep barrier after posthandshake for device {}", connectionContext.getNodeId());
+                LOG.error("failed to get sweep barrier after post-handshake for device {}", connectionContext.getNodeId());
                 connectionContext.closeConnection(false);
             }
         };
index 1bfe9e96a3fe77dc7f11b5b62c9f4a57ae5dd413..558f44cfb57a25e8db25512625f330fcd8e9e129 100644 (file)
@@ -38,6 +38,7 @@ 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.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
 import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
@@ -111,7 +112,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     // TODO: high water mark factor should be parametrized
     private static final float HIGH_WATERMARK_FACTOR = 0.95f;
 
-    private final ConnectionContext primaryConnectionContext;
+    private ConnectionContext primaryConnectionContext;
     private final DeviceState deviceState;
     private final DataBroker dataBroker;
     private final Map<SwitchConnectionDistinguisher, ConnectionContext> auxiliaryConnectionContexts;
@@ -143,7 +144,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             @Nonnull final MessageSpy messageSpy,
             @Nonnull final TranslatorLibrary translatorLibrary,
             @Nonnull final DeviceManager manager,
-           final ConvertorExecutor convertorExecutor) {
+               final ConvertorExecutor convertorExecutor) {
         this.primaryConnectionContext = Preconditions.checkNotNull(primaryConnectionContext);
         this.deviceInfo = primaryConnectionContext.getDeviceInfo();
         this.deviceState = new DeviceStateImpl();
@@ -197,7 +198,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     public void removeAuxiliaryConnectionContext(final ConnectionContext connectionContext) {
         final SwitchConnectionDistinguisher connectionDistinguisher = createConnectionDistinguisher(connectionContext);
         LOG.debug("auxiliary connection dropped: {}, nodeId:{}", connectionContext.getConnectionAdapter()
-                .getRemoteAddress(), getDeviceInfo().getNodeId());
+                .getRemoteAddress(), getDeviceInfo().getLOGValue());
         auxiliaryConnectionContexts.remove(connectionDistinguisher);
     }
 
@@ -286,7 +287,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             // Trigger off a notification
             notificationPublishService.offerNotification(flowRemovedNotification);
         } else if(LOG.isDebugEnabled()) {
-            LOG.debug("For nodeId={} isNotificationFlowRemovedOff={}", getDeviceInfo().getNodeId(), deviceManager.getIsNotificationFlowRemovedOff());
+            LOG.debug("For nodeId={} isNotificationFlowRemovedOff={}", getDeviceInfo().getLOGValue(), deviceManager.getIsNotificationFlowRemovedOff());
         }
 
         final ItemLifecycleListener itemLifecycleListener = flowLifeCycleKeeper.getItemLifecycleListener();
@@ -424,7 +425,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     public synchronized void close() {
         LOG.debug("closing deviceContext: {}, nodeId:{}",
                 getPrimaryConnectionContext().getConnectionAdapter().getRemoteAddress(),
-                getDeviceInfo().getNodeId());
+                getDeviceInfo().getLOGValue());
         // NOOP
         throw new UnsupportedOperationException("Autocloseble.close will be removed soon");
     }
@@ -486,15 +487,15 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public synchronized void shutdownConnection() {
-        LOG.debug("Shutdown method for node {}", getDeviceInfo().getNodeId());
+        LOG.debug("Shutdown method for node {}", getDeviceInfo().getLOGValue());
         if (CONTEXT_STATE.TERMINATION.equals(getState())) {
-            LOG.debug("DeviceCtx for Node {} is in termination process.", getDeviceInfo().getNodeId());
+            LOG.debug("DeviceCtx for Node {} is in termination process.", getDeviceInfo().getLOGValue());
             return;
         }
         setState(CONTEXT_STATE.TERMINATION);
 
         if (ConnectionContext.CONNECTION_STATE.RIP.equals(getPrimaryConnectionContext().getConnectionState())) {
-            LOG.debug("ConnectionCtx for Node {} is in RIP state.", getDeviceInfo().getNodeId());
+            LOG.debug("ConnectionCtx for Node {} is in RIP state.", getDeviceInfo().getLOGValue());
             return;
         }
         /* Terminate Auxiliary Connection */
@@ -537,9 +538,9 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public void startupClusterServices() throws ExecutionException, InterruptedException {
-        LOG.debug("Initializing transaction chain manager for node {}", getDeviceInfo().getNodeId());
+        LOG.debug("Initializing transaction chain manager for node {}", getDeviceInfo().getLOGValue());
         this.transactionChainManager.activateTransactionManager();
-        LOG.debug("Waiting to get node {} information", getDeviceInfo().getNodeId());
+        LOG.debug("Waiting to get node {} information", getDeviceInfo().getLOGValue());
         DeviceInitializationUtils.initializeNodeInformation(this, switchFeaturesMandatory, this.convertorExecutor);
     }
 
@@ -557,4 +558,17 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     public DeviceInfo getDeviceInfo() {
         return this.deviceInfo;
     }
+
+    @Override
+    public void putLifecycleServiceIntoTxChainManager(final LifecycleService lifecycleService){
+        this.transactionChainManager.setLifecycleService(lifecycleService);
+    }
+
+    @Override
+    public void replaceConnectionContext(final ConnectionContext connectionContext){
+        // Act like we are initializing the context
+        setState(CONTEXT_STATE.INITIALIZATION);
+        this.primaryConnectionContext = connectionContext;
+        this.onPublished();
+    }
 }
index 0614df6bd5c2447102208e9cf7c9a29a0fb4fc21..35c372b332fab7a85a1136d1e140016f19265d57 100644 (file)
@@ -9,7 +9,6 @@ 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;
@@ -35,6 +34,7 @@ import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
 import org.opendaylight.openflowplugin.api.openflow.OFPContext;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionStatus;
 import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
@@ -49,7 +49,6 @@ import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionCon
 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.util.DeviceInitializationUtils;
 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;
@@ -100,7 +99,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
                              final ClusterSingletonServiceProvider singletonServiceProvider,
                              final NotificationPublishService notificationPublishService,
                              final HashedWheelTimer hashedWheelTimer,
-                            final ConvertorExecutor convertorExecutor) {
+                             final ConvertorExecutor convertorExecutor) {
         this.switchFeaturesMandatory = switchFeaturesMandatory;
         this.globalNotificationQuota = globalNotificationQuota;
         this.isNotificationFlowRemovedOff = isNotificationFlowRemovedOff;
@@ -145,7 +144,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
     }
 
     @Override
-    public boolean deviceConnected(@CheckForNull final ConnectionContext connectionContext) throws Exception {
+    public ConnectionStatus deviceConnected(@CheckForNull final ConnectionContext connectionContext) throws Exception {
         Preconditions.checkArgument(connectionContext != null);
 
         DeviceInfo deviceInfo = connectionContext.getDeviceInfo();
@@ -157,11 +156,15 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
          if (deviceContexts.containsKey(deviceInfo)) {
              DeviceContext deviceContext = deviceContexts.get(deviceInfo);
              if (!deviceContext.getState().equals(OFPContext.CONTEXT_STATE.TERMINATION)) {
-                 LOG.warn("Context state for node {} is not in TERMINATION state, trying to reconnect", connectionContext.getNodeId().getValue());
+                 LOG.info("Node {} already connected but context state not in TERMINATION state, replacing connection context",
+                         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.getNodeId().getValue());
+                 LOG.warn("Rejecting connection from node which is already connected and there exist deviceContext for it: {}",
+                         connectionContext.getDeviceInfo().getLOGValue());
+                 return ConnectionStatus.CLOSING;
              }
-             return false;
          }
 
         LOG.info("ConnectionEvent: Device connected to controller, Device:{}, NodeId:{}",
@@ -194,6 +197,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
         final LifecycleService lifecycleService = new LifecycleServiceImpl();
         lifecycleService.setDeviceContext(deviceContext);
+        deviceContext.putLifecycleServiceIntoTxChainManager(lifecycleService);
 
         lifecycleServices.putIfAbsent(deviceInfo, lifecycleService);
 
@@ -209,7 +213,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
         connectionAdapter.setMessageListener(messageListener);
         deviceInitPhaseHandler.onDeviceContextLevelUp(connectionContext.getDeviceInfo(), lifecycleService);
-        return true;
+        return ConnectionStatus.MAY_CONTINUE;
     }
 
     private void updatePacketInRateLimiters() {
@@ -255,14 +259,24 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
     @Override
     public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
+
         deviceContexts.remove(deviceInfo);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Device context removed for node {}", deviceInfo.getLOGValue());
+        }
+
         LifecycleService lifecycleService = lifecycleServices.remove(deviceInfo);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Lifecycle service removed for node {}", deviceInfo.getLOGValue());
+        }
+
         updatePacketInRateLimiters();
         if (Objects.nonNull(lifecycleService)) {
             try {
                 lifecycleService.close();
+                LOG.debug("Lifecycle service successfully closed for node {}", deviceInfo.getLOGValue());
             } catch (Exception e) {
-                LOG.warn("Closing service for node {} was unsuccessful ", deviceInfo.getNodeId().getValue(), e);
+                LOG.warn("Closing lifecycle service for node {} was unsuccessful ", deviceInfo.getLOGValue(), e);
             }
         }
     }
@@ -294,7 +308,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         final DeviceContext deviceCtx = this.deviceContexts.get(deviceInfo);
 
         if (null == deviceCtx) {
-            LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.", deviceInfo.getNodeId());
+            LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.", deviceInfo.getLOGValue());
             return;
         }
 
@@ -306,7 +320,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         deviceCtx.setState(OFPContext.CONTEXT_STATE.TERMINATION);
 
         if (!connectionContext.equals(deviceCtx.getPrimaryConnectionContext())) {
-            LOG.debug("Node {} disconnected, but not primary connection.", connectionContext.getDeviceInfo().getNodeId().getValue());
+            LOG.debug("Node {} disconnected, but not primary connection.", connectionContext.getDeviceInfo().getLOGValue());
             /* Connection is not PrimaryConnection so try to remove from Auxiliary Connections */
             deviceCtx.removeAuxiliaryConnectionContext(connectionContext);
         }
@@ -318,13 +332,13 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
                 @Override
                 public void onSuccess(final Void result) {
-                    LOG.debug("TxChainManager for device {} is closed successful.", deviceInfo.getNodeId().getValue());
+                    LOG.debug("TxChainManager for device {} is closed successful.", deviceInfo.getLOGValue());
                     deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
                 }
 
                 @Override
                 public void onFailure(final Throwable t) {
-                    LOG.warn("TxChainManager for device {} failed by closing.", deviceInfo.getNodeId().getValue());
+                    LOG.warn("TxChainManager for device {} failed by closing.", deviceInfo.getLOGValue());
                     LOG.trace("TxChainManager failed by closing. ", t);
                     deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
                 }
@@ -332,7 +346,7 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
             /* Add timer for Close TxManager because it could fain ind cluster without notification */
             final TimerTask timerTask = timeout -> {
                 if (!future.isDone()) {
-                    LOG.warn("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", deviceInfo.getNodeId().getValue());
+                    LOG.warn("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", deviceInfo.getLOGValue());
                     future.cancel(false);
                 }
             };
index 4f28731606934e1778a5d148e71aa869c4a71d32..7ccdc42824ccb132454e54f60500ff5de2cae776 100644 (file)
@@ -14,6 +14,8 @@ 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.Objects;
 import java.util.concurrent.CancellationException;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -54,6 +56,7 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     private final Object txLock = new Object();
     private final KeyedInstanceIdentifier<Node, NodeKey> nodeII;
     private final DataBroker dataBroker;
+    private LifecycleService lifecycleService;
 
     @GuardedBy("txLock")
     private WriteTransaction wTx;
@@ -90,6 +93,10 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
         txChainFactory = dataBroker.createTransactionChain(TransactionChainManager.this);
     }
 
+    public void setLifecycleService(final LifecycleService lifecycleService) {
+        this.lifecycleService = lifecycleService;
+    }
+
     void initialSubmitWriteTransaction() {
         enableSubmit();
         submitWriteTransaction();
@@ -189,6 +196,9 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
                     if (initCommit) {
                         LOG.warn("Initial commit failed. ", t);
                         wTx = null;
+                        if (Objects.nonNull(lifecycleService)) {
+                            lifecycleService.closeConnection();
+                        }
                     }
                 }
             });
index 9dfd74b0d280af4a11e2c7e480c8475bdfadafe6..d5e024a90586f4e1851856e6809fb9f7197dc5af 100644 (file)
@@ -45,7 +45,7 @@ public class LifecycleServiceImpl implements LifecycleService {
         try {
 
             if (LOG.isDebugEnabled()) {
-                LOG.debug("Starting clustering MASTER services for node {}", this.deviceContext.getDeviceInfo().getNodeId().getValue());
+                LOG.debug("Starting clustering MASTER services for node {}", this.deviceContext.getDeviceInfo().getLOGValue());
                 LOG.debug("===============================================");
             }
 
@@ -99,7 +99,7 @@ public class LifecycleServiceImpl implements LifecycleService {
 
     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().getNodeId().getValue());
+            LOG.warn("Node {} was disconnected, will stop starting MASTER services.", this.deviceContext.getDeviceInfo().getLOGValue());
             return true;
         }
         return false;
@@ -107,9 +107,21 @@ public class LifecycleServiceImpl implements LifecycleService {
 
     @Override
     public ListenableFuture<Void> closeServiceInstance() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Stopping clustering MASTER services for node {}", this.deviceContext.getDeviceInfo().getLOGValue());
+            LOG.debug("===============================================");
+        }
+
+        LOG.info("Stopping role context cluster services for node {}", getIdentifier());
         roleContext.stopClusterServices();
+
+        LOG.info("Stopping statistics context cluster services for node {}", getIdentifier());
         statContext.stopClusterServices();
+
+        LOG.info("Stopping rpc context cluster services for node {}", getIdentifier());
         rpcContext.stopClusterServices();
+
+        LOG.info("Stopping device context cluster services for node {}", getIdentifier());
         return deviceContext.stopClusterServices();
     }
 
@@ -187,16 +199,16 @@ public class LifecycleServiceImpl implements LifecycleService {
                             .filter(Objects::nonNull)
                             .count();
 
-                    LOG.debug("Finished filling flow registry with {} flows for node: {}", flowCount, getIdentifier());
+                    LOG.debug("Finished filling flow registry with {} flows for node: {}", flowCount, deviceContext.getDeviceInfo().getLOGValue());
                 }
             }
 
             @Override
             public void onFailure(Throwable t) {
                 if (deviceFlowRegistryFill.isCancelled()) {
-                    LOG.debug("Cancelled filling flow registry with flows for node: {}", getIdentifier());
+                    LOG.debug("Cancelled filling flow registry with flows for node: {}", deviceContext.getDeviceInfo().getLOGValue());
                 } else {
-                    LOG.warn("Failed filling flow registry with flows for node: {} with exception: {}", getIdentifier(), t);
+                    LOG.warn("Failed filling flow registry with flows for node: {} with exception: {}", deviceContext.getDeviceInfo().getLOGValue(), t);
                 }
             }
         });
index 263d8e7098319f877fb7716845ce7dce5a50e2b4..45141930493634968720268710b4c4de571f898c 100644 (file)
@@ -73,18 +73,18 @@ public class RoleManagerImpl implements RoleManager {
         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.getNodeId());
+        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.getNodeId().getValue());
+                            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.getNodeId().getValue());
+                        LOG.warn("Was not able to set role SLAVE to device on node {} ",deviceInfo.getLOGValue());
                         lifecycleService.closeConnection();
                     }
                 });
@@ -118,7 +118,7 @@ public class RoleManagerImpl implements RoleManager {
         Futures.addCallback(delFuture, new FutureCallback<Void>() {
             @Override
             public void onSuccess(final Void result) {
-                LOG.debug("Delete Node {} was successful", deviceInfo);
+                LOG.debug("Delete Node {} was successful", deviceInfo.getLOGValue());
                 contexts.remove(deviceInfo);
             }
 
@@ -128,14 +128,14 @@ public class RoleManagerImpl implements RoleManager {
                 if (numRetries > 0) {
                     // We "used" one retry here, so decrement it
                     final int curRetries = numRetries - 1;
-                    LOG.debug("Delete node {} failed with exception {}. Trying again (retries left: {})", deviceInfo.getNodeId(), t, curRetries);
+                    LOG.debug("Delete node {} failed with exception {}. Trying again (retries left: {})", deviceInfo.getLOGValue(), t, curRetries);
                     // Recursive call to this method with "one less" retry
                     removeDeviceFromOperationalDS(deviceInfo, curRetries);
                     return;
                 }
 
                 // No retries left, so we will just close the role context, and ignore datastore cleanup
-                LOG.warn("Delete node {} failed with exception {}. No retries left, aborting", deviceInfo.getNodeId(), t);
+                LOG.warn("Delete node {} failed with exception {}. No retries left, aborting", deviceInfo.getLOGValue(), t);
                 contexts.remove(deviceInfo);
             }
         });
index 4d41dc59b94e61965a507c7a56a5d41e44eff463..22c4e18693d3d1c4458701265eaddbf36d63924a 100644 (file)
@@ -97,7 +97,7 @@ public class RpcManagerImpl implements RpcManager {
     public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
         final RpcContext removedContext = contexts.remove(deviceInfo);
         if (removedContext != null) {
-            LOG.info("Unregister RPCs services for device context closure");
+            LOG.debug("Unregister RPCs services for  node {}", deviceInfo.getLOGValue());
             removedContext.close();
         }
         deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
index 68cee5bde57fa715a7d50e9c2a8fdbfa3f8c29bb..98e6d993e42abe188772aa33c6c2445398bb4661 100644 (file)
@@ -96,7 +96,7 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
     public void onDeviceContextLevelUp(final DeviceInfo deviceInfo, final LifecycleService lifecycleService) throws Exception {
 
         final StatisticsContext statisticsContext = new StatisticsContextImpl(deviceInfo, isStatisticsPollingEnabled, lifecycleService, convertorExecutor, this);
-        Verify.verify(contexts.putIfAbsent(deviceInfo, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", deviceInfo.getNodeId());
+        Verify.verify(contexts.putIfAbsent(deviceInfo, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", deviceInfo.getLOGValue());
         lifecycleService.setStatContext(statisticsContext);
         deviceInitPhaseHandler.onDeviceContextLevelUp(deviceInfo, lifecycleService);
     }
@@ -142,7 +142,7 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
         final long STATS_TIMEOUT_SEC = averageTime > 0 ? 3 * averageTime : DEFAULT_STATS_TIMEOUT_SEC;
         final TimerTask timerTask = timeout -> {
             if (!deviceStatisticsCollectionFuture.isDone()) {
-                LOG.info("Statistics collection for node {} still in progress even after {} secs", deviceInfo.getNodeId(), STATS_TIMEOUT_SEC);
+                LOG.info("Statistics collection for node {} still in progress even after {} secs", deviceInfo.getLOGValue(), STATS_TIMEOUT_SEC);
                 deviceStatisticsCollectionFuture.cancel(true);
             }
         };
@@ -194,7 +194,7 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
     public void onDeviceContextLevelDown(final DeviceInfo deviceInfo) {
         final StatisticsContext statisticsContext = contexts.remove(deviceInfo);
         if (null != statisticsContext) {
-            LOG.trace("Removing device context from stack. No more statistics gathering for device: {}", deviceInfo.getNodeId());
+            LOG.debug("Removing device context from stack. No more statistics gathering for device: {}", deviceInfo.getLOGValue());
             statisticsContext.close();
         }
         deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceInfo);
index b20a4f999e6b915a71e22e681c486e91844afa9a..4eab2e2f04c8082e9183d952cf567cdfd5ae7eef 100644 (file)
@@ -97,6 +97,7 @@ public class HandshakeListenerImplTest {
     @Test
     public void testOnHandshakeFailure2() throws Exception {
         Mockito.when(connectionAdapter.getRemoteAddress()).thenReturn(InetSocketAddress.createUnresolved("ut-ofp.example.org", 4242));
+        connectionContextSpy.setNodeId(new NodeId("openflow:1"));
         handshakeListener.onHandshakeFailure();
         Mockito.verify(handshakeContext).close();
         Mockito.verify(connectionContextSpy).closeConnection(false);
index 9da0d86795f90097dba9880680fb7e80bb736697..69e945976a9bc5b278215a9791b0a8eab4777329 100644 (file)
@@ -29,6 +29,8 @@ import io.netty.util.Timeout;
 import java.math.BigInteger;
 import java.net.InetSocketAddress;
 import java.util.concurrent.atomic.AtomicLong;
+
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -538,4 +540,17 @@ public class DeviceContextImplTest {
         assertEquals(0, deviceContext.getDeviceMeterRegistry().getAllMeterIds().size());
 
     }
+
+    @Test
+    public void replaceConnectionContext() throws Exception {
+
+        final ConnectionContext connectionContext1 = mock(ConnectionContext.class);
+        Assert.assertEquals(deviceContext.getPrimaryConnectionContext(), connectionContext);
+        Mockito.when(connectionContext1.getConnectionAdapter()).thenReturn(connectionAdapter);
+        Mockito.doNothing().when(connectionAdapter).setPacketInFiltering(Mockito.anyBoolean());
+        deviceContext.replaceConnectionContext(connectionContext1);
+        Assert.assertEquals(deviceContext.getPrimaryConnectionContext(), connectionContext1);
+
+    }
+
 }