*/
package org.opendaylight.openflowplugin.impl.role;
+import javax.annotation.Nullable;
+import java.util.concurrent.Future;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
-import java.util.concurrent.Future;
-import javax.annotation.Nullable;
+import com.google.common.util.concurrent.SettableFuture;
import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
public class RoleContextImpl implements RoleContext {
private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
- private EntityOwnershipService entityOwnershipService;
+ private final EntityOwnershipService entityOwnershipService;
private EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
private final RpcProviderRegistry rpcProviderRegistry;
- private DeviceContext deviceContext;
- private Entity entity;
- private OpenflowOwnershipListener openflowOwnershipListener;
+ private final DeviceContext deviceContext;
+ private final Entity entity;
+ private final OpenflowOwnershipListener openflowOwnershipListener;
private SalRoleService salRoleService;
private FutureCallback<Boolean> roleChangeCallback;
+ private final SettableFuture<OfpRole> initRoleChangeFuture;
- public RoleContextImpl(DeviceContext deviceContext, RpcProviderRegistry rpcProviderRegistry,
- EntityOwnershipService entityOwnershipService, OpenflowOwnershipListener openflowOwnershipListener) {
+ public RoleContextImpl(final DeviceContext deviceContext, final RpcProviderRegistry rpcProviderRegistry,
+ final EntityOwnershipService entityOwnershipService, final OpenflowOwnershipListener openflowOwnershipListener) {
this.entityOwnershipService = entityOwnershipService;
this.rpcProviderRegistry = rpcProviderRegistry;
this.deviceContext = deviceContext;
this.openflowOwnershipListener = openflowOwnershipListener;
salRoleService = new SalRoleServiceImpl(this, deviceContext);
- //make a call to entity ownership service and listen for notifications from the service
- requestOpenflowEntityOwnership();
+ initRoleChangeFuture = SettableFuture.create();
}
@Override
- public void facilitateRoleChange(FutureCallback<Boolean> roleChangeCallback) {
+ public Future<OfpRole> initialization() throws CandidateAlreadyRegisteredException {
+ LOG.debug("Initialization requestOpenflowEntityOwnership for entity {}", entity);
+ openflowOwnershipListener.registerRoleChangeListener(this);
+ entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity);
+ LOG.info("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext
+ .getPrimaryConnectionContext().getNodeId().getValue());
+ return initRoleChangeFuture;
+ }
+
+ /**
+ * @deprecated not used but we are able to add here extra call for get EntityOwnershipState from
+ * OpenflowOwnershipListener instead call it directly from RoleManager (here could be
+ * add call salRoleService.setRole(setRoleInput);
+ */
+ @Override
+ @Deprecated
+ public void facilitateRoleChange(final FutureCallback<Boolean> roleChangeCallback) {
this.roleChangeCallback = roleChangeCallback;
if (!isDeviceConnected()) {
throw new IllegalStateException(
}
}
+ /**
+ * @deprecated not used
+ */
+ @Deprecated
private void requestOpenflowEntityOwnership() {
LOG.debug("requestOpenflowEntityOwnership for entity {}", entity);
// The role change listener must be registered after registering a candidate
openflowOwnershipListener.registerRoleChangeListener(this);
LOG.info("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext.getPrimaryConnectionContext().getNodeId().getValue());
- } catch (CandidateAlreadyRegisteredException e) {
+ } catch (final CandidateAlreadyRegisteredException e) {
// we can log and move for this error, as listener is present and role changes will be served.
LOG.error("Candidate - Entity already registered with Openflow candidate ", entity, e );
}
@Override
public void onRoleChanged(final OfpRole oldRole, final OfpRole newRole) {
+ LOG.trace("onRoleChanged method call for Entity {}", entity);
+
+ if (!isDeviceConnected()) {
+ // this can happen as after the disconnect, we still get a last messsage from EntityOwnershipService.
+ LOG.info("Device {} is disconnected from this node. Hence not attempting a role change.",
+ deviceContext.getPrimaryConnectionContext().getNodeId());
+ if (!initRoleChangeFuture.isDone()) {
+ LOG.debug("RoleChange is not valid for initialization Entity {} anymore - Device is disconnected", entity);
+ initRoleChangeFuture.cancel(true);
+ }
+ return;
+ }
- // called notification thread from md-sal
+ if (!initRoleChangeFuture.isDone()) {
+ LOG.debug("Initialization Role for entity {} is chosed {}", entity, newRole);
+ initRoleChangeFuture.set(newRole);
+ }
LOG.debug("Role change received from ownership listener from {} to {} for device:{}", oldRole, newRole,
deviceContext.getPrimaryConnectionContext().getNodeId());
.setNode(new NodeRef(deviceContext.getDeviceState().getNodeInstanceIdentifier()))
.build();
- Future<RpcResult<SetRoleOutput>> setRoleOutputFuture = salRoleService.setRole(setRoleInput);
+ final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture = salRoleService.setRole(setRoleInput);
Futures.addCallback(JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture), new FutureCallback<RpcResult<SetRoleOutput>>() {
@Override
- public void onSuccess(RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
+ public void onSuccess(final RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
LOG.debug("Rolechange {} successful made on switch :{}", newRole,
deviceContext.getPrimaryConnectionContext().getNodeId());
deviceContext.getDeviceState().setRole(newRole);
}
@Override
- public void onFailure(Throwable throwable) {
+ public void onFailure(final Throwable throwable) {
LOG.error("Error in setRole {} for device {} ", newRole,
deviceContext.getPrimaryConnectionContext().getNodeId(), throwable);
if (roleChangeCallback != null) {
public void close() throws Exception {
if (entityOwnershipCandidateRegistration != null) {
LOG.debug("Closing EntityOwnershipCandidateRegistration for {}", entity);
- LOG.error("Who called this close?????", new Throwable());
entityOwnershipCandidateRegistration.close();
}
}
@Override
- public void onDeviceContextClosed(DeviceContext deviceContext) {
+ public void onDeviceContextClosed(final DeviceContext deviceContext) {
try {
LOG.debug("onDeviceContextClosed called");
this.close();
- } catch (Exception e) {
+ } catch (final Exception e) {
LOG.error("Exception in onDeviceContextClosed of RoleContext", e);
}
}
}
@Override
- public void onDeviceDisconnectedFromCluster() {
+ public void onDeviceDisconnectedFromCluster(final boolean removeNodeFromDS) {
LOG.debug("Called onDeviceDisconnectedFromCluster in DeviceContext for entity:{}", entity);
- deviceContext.onDeviceDisconnectedFromCluster();
+ deviceContext.onDeviceDisconnectedFromCluster(removeNodeFromDS);
}
private boolean isDeviceConnected() {
}
@VisibleForTesting
- public void setSalRoleService(SalRoleService salRoleService) {
+ public void setSalRoleService(final SalRoleService salRoleService) {
this.salRoleService = salRoleService;
}
}