Merge "BUG-6890: Edit to cfg file reflecting that statistics collection is turned...
authorAbhijit Kumbhare <abhijit.kumbhare@ericsson.com>
Mon, 24 Oct 2016 05:18:35 +0000 (05:18 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 24 Oct 2016 05:18:35 +0000 (05:18 +0000)
20 files changed:
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceManager.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/LifecycleService.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleContext.java [deleted file]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleManager.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.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/lifecycle/LifecycleServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImpl.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalFlowServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtils.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/LifecycleServiceImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleContextImplTest.java [deleted file]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImplTest.java [deleted file]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtilsTest.java

index 676c21c780ba112cc69264d4d2b192c0b30d58e1..1f8c692b498c33eee73063391192d3eee8c7288c 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.util.concurrent.ListenableFuture;
 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;
@@ -21,6 +22,9 @@ 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;
+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
@@ -41,7 +45,8 @@ public interface DeviceContext extends
         AutoCloseable,
         DeviceReplyProcessor,
         TxFacade,
-        DeviceRegistry{
+        DeviceRegistry,
+        RequestContextStack{
 
     /**
      * Method close all auxiliary connections and primary connection.
@@ -132,5 +137,17 @@ public interface DeviceContext extends
     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();
 }
 
index 51f4ee680cf577467bb0068f3dd2a91b3356aa54..c56409a6da4f34c9d6db39d5af61ff30567cecf2 100644 (file)
@@ -8,6 +8,8 @@
 
 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;
@@ -39,5 +41,6 @@ public interface DeviceManager extends DeviceConnectedHandler, DeviceDisconnecte
 
     void setBarrierInterval(long barrierTimeoutLimit);
 
+    CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(DeviceInfo deviceInfo);
 }
 
index 3084568e3c687cd6d3395b7553afd9fe8e0eafd5..c3e35491c18f09acd05d25939715d2caf2cd24ea 100644 (file)
@@ -13,7 +13,6 @@ 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;
 
@@ -40,12 +39,6 @@ public interface LifecycleService extends ClusterSingletonService, AutoCloseable
      */
     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
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleContext.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleContext.java
deleted file mode 100644 (file)
index 1296d75..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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();
-}
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleManager.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleManager.java
deleted file mode 100644 (file)
index 9bc4c88..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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);
-
-}
index 917d8a93dadb59095e165d4438a742ec63a342d4..4aa1ee04437e353f39f777212c8a065176a593b6 100644 (file)
@@ -38,7 +38,6 @@ import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionPro
 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;
@@ -48,7 +47,6 @@ import org.opendaylight.openflowplugin.extension.api.OpenFlowPluginExtensionRegi
 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;
@@ -82,7 +80,6 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
     private int barrierCountLimit;
     private long echoReplyTimeout;
     private DeviceManager deviceManager;
-    private RoleManager roleManager;
     private RpcManager rpcManager;
     private RpcProviderRegistry rpcProviderRegistry;
     private StatisticsManager statisticsManager;
@@ -245,7 +242,6 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
         ((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 */
@@ -253,14 +249,12 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
         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);
 
@@ -358,10 +352,6 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
         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();
     }
index c7d60e6f9a06260992149bd406792475f50e01f2..dd13831464e0217accb78cc4ebf49863fc8697d1 100644 (file)
@@ -8,12 +8,17 @@
 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;
@@ -21,7 +26,10 @@ import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
+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;
@@ -30,6 +38,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosed
 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;
@@ -65,6 +74,7 @@ import org.opendaylight.openflowplugin.impl.registry.flow.DeviceFlowRegistryImpl
 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;
@@ -95,9 +105,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter
 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;
 
@@ -111,10 +127,16 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     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 static final Long RETRY_DELAY = 100L;
     private static final int RETRY_COUNT = 3;
 
+    private SalRoleService salRoleService = null;
+    private final HashedWheelTimer hashedWheelTimer;
     private ConnectionContext primaryConnectionContext;
     private final DeviceState deviceState;
     private final DataBroker dataBroker;
@@ -141,6 +163,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     private final ConvertorExecutor convertorExecutor;
     private volatile CONTEXT_STATE state;
     private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
+    private final DeviceManager myManager;
 
     DeviceContextImpl(
             @Nonnull final ConnectionContext primaryConnectionContext,
@@ -149,9 +172,13 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             @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<>();
@@ -602,9 +629,49 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @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
@@ -637,6 +704,11 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         return this.skipTableFeatures;
     }
 
+    @Override
+    public void setSalRoleService(@Nonnull SalRoleService salRoleService) {
+        this.salRoleService = salRoleService;
+    }
+
     @Override
     public void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler) {
         this.clusterInitializationPhaseHandler = handler;
@@ -663,6 +735,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             return false;
         }
 
+        Futures.addCallback(sendRoleChangeToDevice(OfpRole.BECOMEMASTER), new RpcResultFutureCallback());
+
         return this.clusterInitializationPhaseHandler.onContextInstantiateService(getPrimaryConnectionContext());
     }
 
@@ -679,4 +753,58 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             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();
+        }
+    }
 }
index a3c51799ce028b92e1f0e06b8a64323063f0c832..964ad0ba6b9fb41f3064361ee2f3d13ae05a34a3 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.openflowplugin.impl.device;
 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;
@@ -26,10 +27,12 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
 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;
@@ -50,11 +53,14 @@ 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.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;
 
@@ -186,6 +192,8 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
                 connectionAdapter.registerOutboundQueueHandler(outboundQueueProvider, barrierCountLimit, barrierIntervalNanos);
         connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
 
+        final LifecycleService lifecycleService = new LifecycleServiceImpl();
+
         final DeviceContext deviceContext = new DeviceContextImpl(
                 connectionContext,
                 dataBroker,
@@ -193,16 +201,20 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
                 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);
@@ -218,24 +230,6 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         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;
@@ -387,4 +381,74 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         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();
+    }
+
+
 }
index 7b6cbe58eed8d29efae56bc0d415260872e158d1..885438df440cd099277c3ab7f47c517c88680ce8 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.openflowplugin.impl.lifecycle;
 
+import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Objects;
@@ -22,7 +24,6 @@ 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;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -33,9 +34,9 @@ public class LifecycleServiceImpl implements LifecycleService {
 
     private static final Logger LOG = LoggerFactory.getLogger(LifecycleServiceImpl.class);
 
+    private boolean inClosing = false;
     private DeviceContext deviceContext;
     private RpcContext rpcContext;
-    private RoleContext roleContext;
     private StatisticsContext statContext;
     private ClusterSingletonServiceRegistration registration;
     private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
@@ -43,7 +44,6 @@ public class LifecycleServiceImpl implements LifecycleService {
 
     @Override
     public void instantiateServiceInstance() {
-
         LOG.info("Starting clustering MASTER services for node {}", this.deviceContext.getDeviceInfo().getLOGValue());
 
         if (!this.clusterInitializationPhaseHandler.onContextInstantiateService(null)) {
@@ -54,8 +54,7 @@ public class LifecycleServiceImpl implements LifecycleService {
 
     @Override
     public ListenableFuture<Void> closeServiceInstance() {
-
-        LOG.info("Stopping clustering MASTER services for node {}", this.deviceContext.getDeviceInfo().getLOGValue());
+        LOG.info("Closing clustering MASTER services for node {}", this.deviceContext.getDeviceInfo().getLOGValue());
 
         final boolean connectionInterrupted =
                 this.deviceContext
@@ -63,11 +62,31 @@ public class LifecycleServiceImpl implements LifecycleService {
                         .getConnectionState()
                         .equals(ConnectionContext.CONNECTION_STATE.RIP);
 
-        roleContext.stopClusterServices(connectionInterrupted);
-        statContext.stopClusterServices(connectionInterrupted);
-        rpcContext.stopClusterServices(connectionInterrupted);
-        return deviceContext.stopClusterServices(connectionInterrupted);
+        // If connection was interrupted and we are not trying to close service, then we received something
+        // we do not wanted to receive, so do not continue
+        if (connectionInterrupted && !inClosing) {
+            LOG.warn("Failed to close clustering MASTER services for node {} because they are already closed",
+                    LifecycleServiceImpl.this.deviceContext.getDeviceInfo().getLOGValue());
+
+            return Futures.immediateCancelledFuture();
+        }
 
+        // Chain all jobs that will stop our services
+        final List<ListenableFuture<Void>> futureList = new ArrayList<>();
+        futureList.add(statContext.stopClusterServices(connectionInterrupted));
+        futureList.add(rpcContext.stopClusterServices(connectionInterrupted));
+        futureList.add(deviceContext.stopClusterServices(connectionInterrupted));
+
+        // When we stopped all jobs then we are not in closing state anymore (at least from plugin perspective)
+        return Futures.transform(Futures.successfulAsList(futureList), new Function<List<Void>, Void>() {
+            @Nullable
+            @Override
+            public Void apply(@Nullable List<Void> input) {
+                LOG.debug("Closed clustering MASTER services for node {}",
+                        LifecycleServiceImpl.this.deviceContext.getDeviceInfo().getLOGValue());
+                return null;
+            }
+        });
     }
 
     @Override
@@ -78,8 +97,9 @@ public class LifecycleServiceImpl implements LifecycleService {
 
     @Override
     public void close() throws Exception {
-        if (registration != null) {
-            LOG.info("Unregistering clustering MASTER services for node {}", this.deviceContext.getDeviceInfo().getLOGValue());
+        // If we are still registered and we are not already closing, then close the registration
+        if (Objects.nonNull(registration) && !inClosing) {
+            inClosing = true;
             registration.close();
             registration = null;
         }
@@ -93,8 +113,7 @@ public class LifecycleServiceImpl implements LifecycleService {
         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
@@ -111,11 +130,6 @@ public class LifecycleServiceImpl implements LifecycleService {
         this.rpcContext = rpcContext;
     }
 
-    @Override
-    public void setRoleContext(final RoleContext roleContext) {
-        this.roleContext = roleContext;
-    }
-
     @Override
     public void setStatContext(final StatisticsContext statContext) {
         this.statContext = statContext;
@@ -132,8 +146,7 @@ public class LifecycleServiceImpl implements LifecycleService {
     }
 
     private void fillDeviceFlowRegistry() {
-        
-       final ListenableFuture<List<Optional<FlowCapableNode>>> deviceFlowRegistryFill = deviceContext.getDeviceFlowRegistry().fill();
+        final ListenableFuture<List<Optional<FlowCapableNode>>> deviceFlowRegistryFill = deviceContext.getDeviceFlowRegistry().fill();
         Futures.addCallback(deviceFlowRegistryFill, new DeviceFlowRegistryCallback(deviceFlowRegistryFill));
     }
 
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java
deleted file mode 100644 (file)
index 58d8ab2..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/**
- * 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 5 sec", newRole, deviceInfo.getLOGValue());
-                    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();
-        }
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImpl.java
deleted file mode 100644 (file)
index 28191b5..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * 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);
-    }
-
-}
index 730997cb9576b602eab3fc986489d3f6355ddc1e..5f032a70435daedf563c3690e012d9ca0d7e507f 100644 (file)
@@ -45,7 +45,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.Upda
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
 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.FlowModInputBuilder;
@@ -223,45 +222,38 @@ public class SalFlowServiceImpl implements SalFlowService, ItemLifeCycleSource {
 
         @Override
         public void onSuccess(final RpcResult<UpdateFlowOutput> o) {
-            final UpdatedFlow updated = input.getUpdatedFlow();
-            final OriginalFlow original = input.getOriginalFlow();
-            FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(original);
-
-            FlowRegistryKey updatedflowRegistryKey = FlowRegistryKeyFactory.create(updated);
-            final FlowRef flowRef = input.getFlowRef();
             final DeviceFlowRegistry deviceFlowRegistry = deviceContext.getDeviceFlowRegistry();
 
-            if (flowRef == null) {
-                // then this is equivalent to a delete
-                deviceFlowRegistry.removeDescriptor(flowRegistryKey);
+            final UpdatedFlow updated = input.getUpdatedFlow();
+            final OriginalFlow original = input.getOriginalFlow();
+            final FlowRegistryKey origFlowRegistryKey = FlowRegistryKeyFactory.create(original);
+            final FlowRegistryKey updatedFlowRegistryKey = FlowRegistryKeyFactory.create(updated);
+            final FlowDescriptor origFlowDescriptor = deviceFlowRegistry.retrieveIdForFlow(origFlowRegistryKey);
+
+            final boolean isUpdate = Objects.nonNull(origFlowDescriptor);
+            final FlowId fLowId = Objects.nonNull(input.getFlowRef())
+                    ? input.getFlowRef().getValue().firstKeyOf(Flow.class).getId()
+                    : isUpdate ? origFlowDescriptor.getFlowId() : deviceFlowRegistry.storeIfNecessary(updatedFlowRegistryKey);
+            final FlowDescriptor updatedFlowDescriptor = FlowDescriptorFactory.create(updated.getTableId(), fLowId);
+            if (isUpdate) {
+                deviceFlowRegistry.removeDescriptor(origFlowRegistryKey);
+                deviceFlowRegistry.store(updatedFlowRegistryKey, updatedFlowDescriptor);
+            }
 
-                if (itemLifecycleListener != null) {
-                    final FlowDescriptor flowDescriptor =
-                            deviceContext.getDeviceFlowRegistry().retrieveIdForFlow( flowRegistryKey);
-                    KeyedInstanceIdentifier<Flow, FlowKey> flowPath = createFlowPath(flowDescriptor,
-                            deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
-                    itemLifecycleListener.onRemoved(flowPath);
-                }
-            } else {
-                // this is either an add or an update
-                final FlowId flowId = flowRef.getValue().firstKeyOf(Flow.class, FlowKey.class).getId();
-                final FlowDescriptor flowDescriptor = FlowDescriptorFactory.create(updated.getTableId(), flowId);
+            if (itemLifecycleListener != null) {
+                final KeyedInstanceIdentifier<Flow, FlowKey> flowPath =
+                        createFlowPath(
+                                updatedFlowDescriptor,
+                                deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
 
-                deviceFlowRegistry.update(updatedflowRegistryKey, flowDescriptor);
+                final Flow flow = new FlowBuilder(updated)
+                        .setId(updatedFlowDescriptor.getFlowId())
+                        .build();
 
-                if (itemLifecycleListener != null) {
-                    KeyedInstanceIdentifier<Flow, FlowKey> flowPath = createFlowPath(flowDescriptor,
-                            deviceContext.getDeviceInfo().getNodeInstanceIdentifier());
-                    final FlowBuilder flowBuilder = new FlowBuilder(
-                            input.getUpdatedFlow()).setId(flowDescriptor.getFlowId());
-
-                    boolean isUpdate = null !=
-                            deviceFlowRegistry.retrieveIdForFlow(flowRegistryKey);
-                    if (isUpdate) {
-                        itemLifecycleListener.onUpdated(flowPath, flowBuilder.build());
-                    } else {
-                        itemLifecycleListener.onAdded(flowPath, flowBuilder.build());
-                    }
+                if (Objects.nonNull(origFlowDescriptor)) {
+                    itemLifecycleListener.onUpdated(flowPath, flow);
+                } else {
+                    itemLifecycleListener.onAdded(flowPath, flow);
                 }
             }
         }
index 9cd9f1003e9c79ad15a7af5276183340a8ffb1fa..0a2e522cec8f6ba49c959b34a654b8176eaf8199 100644 (file)
@@ -21,6 +21,7 @@ import java.text.SimpleDateFormat;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -31,6 +32,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
 import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
@@ -283,13 +285,18 @@ public final class StatisticsGatheringUtils {
 
                     final short tableId = flowStat.getTableId();
                     final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
-                    final FlowId flowId = registry.storeIfNecessary(flowRegistryKey);
-
-                    final FlowKey flowKey = new FlowKey(flowId);
-                    flowBuilder.setKey(flowKey);
-                    final TableKey tableKey = new TableKey(tableId);
-                    final InstanceIdentifier<Flow> flowIdent = fNodeIdent.child(Table.class, tableKey).child(Flow.class, flowKey);
-                    txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build());
+                    final FlowDescriptor flowDescriptor = registry.retrieveIdForFlow(flowRegistryKey);
+
+                    if(Objects.nonNull(flowDescriptor)) {
+                        final FlowId flowId = flowDescriptor.getFlowId();
+                        final FlowKey flowKey = new FlowKey(flowId);
+                        flowBuilder.setKey(flowKey);
+                        final TableKey tableKey = new TableKey(tableId);
+                        final InstanceIdentifier<Flow> flowIdent = fNodeIdent.child(Table.class, tableKey).child(Flow.class, flowKey);
+                        txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build());
+                    } else {
+                        LOG.warn("Skip write statistics. Flow hash: {} not present in DeviceFlowRegistry", flowRegistryKey.hashCode());
+                    }
                 }
             }
         } catch (Exception e) {
index 4e77150fbeceaa19a0d829c770f62cb15c8bde0f..35cc8356db5d030945caf3f975e45be2da011629 100644 (file)
@@ -232,7 +232,7 @@ public class DeviceContextImplTest {
                 translatorLibrary,
                 deviceManager,
                 convertorExecutor,
-                false);
+                false, timer, deviceManager);
         deviceContextSpy = Mockito.spy(deviceContext);
 
         xid = new Xid(atomicLong.incrementAndGet());
@@ -245,12 +245,12 @@ public class DeviceContextImplTest {
 
     @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
index ab12828ef2634fb1a13681fdf0e89650377e1b89..82ee4b06720638465882f5da060dbbd5cc172461 100644 (file)
@@ -31,6 +31,7 @@ import org.mockito.InOrder;
 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;
@@ -64,12 +65,15 @@ import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorM
 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 {
@@ -109,7 +113,8 @@ public class DeviceManagerImplTest {
     private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
     @Mock
     private ConvertorExecutor convertorExecutor;
-
+    @Mock
+    private KeyedInstanceIdentifier<Node, NodeKey> key;
     @Before
     public void setUp() throws Exception {
         OpenflowPortsUtil.init();
index 96f4dcecdf92d386fbe9693b396b8e142d2ceac1..8ac5337d5fdeb2e1f34b06452ce34900d66ed109 100644 (file)
@@ -20,10 +20,8 @@ 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.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;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
 
@@ -40,8 +38,6 @@ public class LifecycleServiceImplTest {
     @Mock
     private RpcContext rpcContext;
     @Mock
-    private RoleContext roleContext;
-    @Mock
     private StatisticsContext statContext;
     @Mock
     private ConnectionContext connectionContext;
@@ -62,10 +58,13 @@ public class LifecycleServiceImplTest {
         Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
         Mockito.when(deviceInfo.getLOGValue()).thenReturn(TEST_NODE);
 
+        Mockito.when(deviceContext.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);
     }
@@ -73,11 +72,10 @@ public class LifecycleServiceImplTest {
     @Test
     public void instantiateServiceInstance() throws Exception {
         lifecycleService.instantiateServiceInstance();
-        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());
+        Mockito.verify(deviceContext).setLifecycleInitializationPhaseHandler(Mockito.any());
+        Mockito.verify(statContext).setLifecycleInitializationPhaseHandler(Mockito.any());
+        Mockito.verify(statContext).setInitialSubmitHandler(Mockito.any());
+        Mockito.verify(rpcContext).setLifecycleInitializationPhaseHandler(Mockito.any());
     }
 
     @Test
@@ -86,7 +84,6 @@ public class LifecycleServiceImplTest {
         Mockito.verify(statContext).stopClusterServices(false);
         Mockito.verify(deviceContext).stopClusterServices(false);
         Mockito.verify(rpcContext).stopClusterServices(false);
-        Mockito.verify(roleContext).stopClusterServices(false);
     }
 
     @Test
@@ -100,4 +97,4 @@ public class LifecycleServiceImplTest {
         Mockito.verify(deviceContext).shutdownConnection();
     }
 
-}
\ No newline at end of file
+}
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleContextImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleContextImplTest.java
deleted file mode 100644 (file)
index 4234aa9..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * 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);
-    }
-
-}
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImplTest.java
deleted file mode 100644 (file)
index c1e29b7..0000000
+++ /dev/null
@@ -1,150 +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.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
index 9cef7daae3e4cdcb313d4fd3d2a0a5dceb6dd9ef..098ef4dd866e6061fae6f2ad3590a0f16a78dfa5 100644 (file)
@@ -40,6 +40,7 @@ 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.registry.flow.DeviceFlowRegistry;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
@@ -105,6 +106,8 @@ public class MultipartRequestOnTheFlyCallbackTest {
     @Mock
     private DeviceFlowRegistry mockedFlowRegistry;
     @Mock
+    private FlowDescriptor mockedFlowDescriptor;
+    @Mock
     private ReadOnlyTransaction mockedReadOnlyTx;
 
     private AbstractRequestContext<List<MultipartReply>> dummyRequestContext;
@@ -134,6 +137,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
         when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
         when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(mockedFlowRegistry);
+        when(mockedFlowRegistry.retrieveIdForFlow(Matchers.any(FlowRegistryKey.class))).thenReturn(mockedFlowDescriptor);
 
         final InstanceIdentifier<FlowCapableNode> nodePath = mockedDeviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
         final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
@@ -202,7 +206,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
         final MatchBuilder matchBuilder = new MatchBuilder()
                 .setMatchEntry(Collections.<MatchEntry>emptyList());
         final FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder()
-.setTableId(tableId)
+                .setTableId(tableId)
                 .setPriority(2)
                 .setCookie(BigInteger.ZERO)
                 .setByteCount(BigInteger.TEN)
@@ -238,7 +242,6 @@ public class MultipartRequestOnTheFlyCallbackTest {
 
         verify(mockedReadOnlyTx, times(1)).read(LogicalDatastoreType.OPERATIONAL, nodePath);
         verify(mockedReadOnlyTx, times(1)).close();
-        verify(mockedFlowRegistry).storeIfNecessary(Matchers.<FlowRegistryKey> any());
         verify(mockedDeviceContext, times(1)).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL),
                 eq(tableIdent), Matchers.<Table> any());
         /*
index 7076e6b8862d7c97994e3abe69e1fac885c39979..e5cfea5b897874ee3a06a206397638f05d08e2db 100644 (file)
@@ -27,6 +27,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
 import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -41,6 +42,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
@@ -153,6 +155,10 @@ public class StatisticsGatheringUtilsTest {
     @Mock
     private DeviceMeterRegistry deviceMeterRegistry;
     @Mock
+    private FlowDescriptor flowDescriptor;
+    @Mock
+    private FlowId flowId;
+    @Mock
     private GetFeaturesOutput features;
     @Mock
     private ReadOnlyTransaction readTx;
@@ -180,6 +186,7 @@ public class StatisticsGatheringUtilsTest {
         when(deviceContext.getDeviceFlowRegistry()).thenReturn(deviceFlowRegistry);
         when(deviceContext.getDeviceGroupRegistry()).thenReturn(deviceGroupRegistry);
         when(deviceContext.getDeviceMeterRegistry()).thenReturn(deviceMeterRegistry);
+        when(deviceFlowRegistry.retrieveIdForFlow(Matchers.any(FlowRegistryKey.class))).thenReturn(flowDescriptor);
         when(deviceContext.getReadTransaction()).thenReturn(readTx);
         when(txFacade.getReadTransaction()).thenReturn(readTx);
         when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionAdapter);
@@ -413,8 +420,6 @@ public class StatisticsGatheringUtilsTest {
     public void testGatherStatistics_flow() throws Exception {
         final short tableId = 0;
         final MultipartType type = MultipartType.OFPMPFLOW;
-        when(deviceFlowRegistry.storeIfNecessary(Matchers.any(FlowRegistryKey.class)))
-                .thenReturn(new FlowId("openflow:21"));
 
         final InstanceIdentifier<FlowCapableNode> nodePath = deviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
         final TableBuilder tableDataBld = new TableBuilder();
@@ -424,6 +429,7 @@ public class StatisticsGatheringUtilsTest {
         final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
         final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> flowNodeFuture = Futures.immediateCheckedFuture(flowNodeOpt);
         when(readTx.read(LogicalDatastoreType.OPERATIONAL, nodePath)).thenReturn(flowNodeFuture);
+        when(flowDescriptor.getFlowId()).thenReturn(flowId);
 
         final org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder matchBld =
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder()
@@ -449,12 +455,16 @@ public class StatisticsGatheringUtilsTest {
         final FlowBuilder flowBld = new FlowBuilder()
                 .setTableId((short) 0)
                 .setMatch(new MatchBuilder().build());
-        final KeyedInstanceIdentifier<Flow, FlowKey> flowPath = dummyNodePath.augmentation(FlowCapableNode.class)
-                .child(Table.class, new TableKey((short) 0))
-                .child(Flow.class, new FlowKey(new FlowId("openflow:21")));
+        final KeyedInstanceIdentifier<Table, TableKey> tablePath = dummyNodePath.augmentation(FlowCapableNode.class)
+                .child(Table.class, new TableKey((short) 0));
+        final KeyedInstanceIdentifier<Flow, FlowKey> flowPath =  tablePath.child(Flow.class, new FlowKey(flowId));
+
         verify(deviceContext, Mockito.never()).addDeleteToTxChain(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<?>>any());
-        verify(deviceFlowRegistry).storeIfNecessary(FlowRegistryKeyFactory.create(flowBld.build()));
-        verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(flowPath), Matchers.any(Flow.class));
+        verify(deviceFlowRegistry).retrieveIdForFlow(FlowRegistryKeyFactory.create(flowBld.build()));
+
+        final InOrder inOrder = Mockito.inOrder(txFacade);
+        inOrder.verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(tablePath), Matchers.any(Table.class));
+        inOrder.verify(txFacade).writeToTransaction(Matchers.eq(LogicalDatastoreType.OPERATIONAL), Matchers.eq(flowPath), Matchers.any(Flow.class));
     }
 
     @Test