X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Frole%2FRoleContextImpl.java;h=0a1f81095baed3b82ea9f2da1522271bd1a2472c;hb=277d201d5db47620b29a6a69fd99aec539e537eb;hp=7b5d923e69ac21ea16f1c3f81dfcb9fc05906a17;hpb=cbea01d2c1946503b10ae69f0e3e477d2be28c4e;p=openflowplugin.git 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 index 7b5d923e69..0a1f81095b 100644 --- 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 @@ -7,10 +7,14 @@ */ 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; @@ -19,9 +23,10 @@ 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.lifecycle.LifecycleConductor; +import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler; import org.opendaylight.openflowplugin.api.openflow.role.RoleContext; import org.opendaylight.openflowplugin.api.openflow.role.RoleManager; import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext; @@ -37,8 +42,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Role context hold information about entity ownership registration, - * register and unregister candidate (main and tx) + * Role context try to make change device role on device */ class RoleContextImpl implements RoleContext { @@ -47,24 +51,25 @@ class RoleContextImpl implements RoleContext { private static final int MAX_CLEAN_DS_RETRIES = 3; private SalRoleService salRoleService = null; - private final LifecycleConductor conductor; + private final HashedWheelTimer hashedWheelTimer; private final DeviceInfo deviceInfo; private CONTEXT_STATE state; private final RoleManager myManager; + private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler; RoleContextImpl(final DeviceInfo deviceInfo, - final LifecycleConductor lifecycleConductor, + final HashedWheelTimer hashedWheelTimer, final RoleManager myManager) { - this.conductor = lifecycleConductor; this.deviceInfo = deviceInfo; state = CONTEXT_STATE.WORKING; this.myManager = myManager; + this.hashedWheelTimer = hashedWheelTimer; } @Nullable @Override public RequestContext createRequestContext() { - return new AbstractRequestContext(conductor.reserveXidForDeviceMessage(getDeviceInfo())) { + return new AbstractRequestContext(deviceInfo.reserveXidForDeviceMessage()) { @Override public void close() { } @@ -77,11 +82,6 @@ class RoleContextImpl implements RoleContext { this.salRoleService = salRoleService; } - @Override - public SalRoleService getSalRoleService() { - return this.salRoleService; - } - @Override public CONTEXT_STATE getState() { return this.state; @@ -103,26 +103,62 @@ class RoleContextImpl implements RoleContext { } public void startupClusterServices() throws ExecutionException, InterruptedException { - //TODO: Add callback ? - sendRoleChangeToDevice(OfpRole.BECOMEMASTER).get(); + Futures.addCallback(sendRoleChangeToDevice(OfpRole.BECOMEMASTER), new FutureCallback>() { + @Override + public void onSuccess(@Nullable RpcResult 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()); + } + }); } @Override - public ListenableFuture stopClusterServices() { - ListenableFuture future; - try { - //TODO: Add callback - sendRoleChangeToDevice(OfpRole.BECOMESLAVE).get(); - } catch (InterruptedException | ExecutionException e) { - LOG.warn("Send role to device failed ", e); - } finally { - myManager.removeDeviceFromOperationalDS(deviceInfo, MAX_CLEAN_DS_RETRIES); - future = Futures.immediateFuture(null); + public ListenableFuture stopClusterServices(final boolean deviceDisconnected) { + + if (!deviceDisconnected) { + ListenableFuture future = Futures.transform(makeDeviceSlave(), new Function, Void>() { + @Nullable + @Override + public Void apply(@Nullable RpcResult setRoleOutputRpcResult) { + return null; + } + }); + + Futures.addCallback(future, new FutureCallback() { + @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, MAX_CLEAN_DS_RETRIES); + + } + }); + return future; + } else { + return myManager.removeDeviceFromOperationalDS(deviceInfo, MAX_CLEAN_DS_RETRIES); } - return future; } - private ListenableFuture> sendRoleChangeToDevice(final OfpRole newRole) { + @Override + public ListenableFuture> makeDeviceSlave(){ + return sendRoleChangeToDevice(OfpRole.BECOMESLAVE); + } + + @VisibleForTesting + ListenableFuture> sendRoleChangeToDevice(final OfpRole newRole) { LOG.debug("Sending new role {} to device {}", newRole, deviceInfo.getNodeId()); final Future> setRoleOutputFuture; final Short version = deviceInfo.getVersion(); @@ -136,16 +172,45 @@ class RoleContextImpl implements RoleContext { } else { final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole) .setNode(new NodeRef(DeviceStateUtil.createNodeInstanceIdentifier(deviceInfo.getNodeId()))).build(); - setRoleOutputFuture = getSalRoleService().setRole(setRoleInput); + setRoleOutputFuture = this.salRoleService.setRole(setRoleInput); final TimerTask timerTask = timeout -> { if (!setRoleOutputFuture.isDone()) { - LOG.warn("New role {} was not propagated to device {} during 10 sec", newRole, deviceInfo.getNodeId()); + LOG.warn("New role {} was not propagated to device {} during 10 sec", newRole, deviceInfo.getLOGValue()); setRoleOutputFuture.cancel(true); } }; - conductor.newTimeout(timerTask, 10, TimeUnit.SECONDS); + hashedWheelTimer.newTimeout(timerTask, 10, TimeUnit.SECONDS); } return JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture); } + @Override + public void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler) { + this.clusterInitializationPhaseHandler = handler; + } + + @Override + public boolean onContextInstantiateService(final ConnectionContext connectionContext) { + + if (connectionContext.getConnectionState().equals(ConnectionContext.CONNECTION_STATE.RIP)) { + LOG.warn("Connection on device {} was interrupted, will stop starting master services.", deviceInfo.getLOGValue()); + return false; + } + + Futures.addCallback(sendRoleChangeToDevice(OfpRole.BECOMEMASTER), new FutureCallback>() { + @Override + public void onSuccess(@Nullable RpcResult setRoleOutputRpcResult) { + if (LOG.isDebugEnabled()) { + LOG.debug("Role MASTER was successfully set on device, node {}", deviceInfo.getLOGValue()); + } + } + + @Override + public void onFailure(final Throwable throwable) { + LOG.warn("Was not able to set MASTER role on device, node {}", deviceInfo.getLOGValue()); + } + }); + + return this.clusterInitializationPhaseHandler.onContextInstantiateService(connectionContext); + } }