2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.impl.role;
10 import com.google.common.base.Preconditions;
11 import com.google.common.util.concurrent.Futures;
12 import com.google.common.util.concurrent.JdkFutureAdapters;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import io.netty.util.HashedWheelTimer;
15 import io.netty.util.TimerTask;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import java.util.concurrent.TimeUnit;
19 import javax.annotation.Nonnull;
20 import javax.annotation.Nullable;
21 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
22 import org.opendaylight.openflowplugin.api.OFConstants;
23 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
24 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
25 import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
26 import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
27 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
28 import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
35 import org.opendaylight.yangtools.yang.common.RpcResult;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * Role context hold information about entity ownership registration,
41 * register and unregister candidate (main and tx)
43 class RoleContextImpl implements RoleContext {
45 private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
46 // Maximum limit of timeout retries when cleaning DS, to prevent infinite recursive loops
47 private static final int MAX_CLEAN_DS_RETRIES = 3;
49 private SalRoleService salRoleService = null;
50 private final HashedWheelTimer hashedWheelTimer;
51 private final DeviceInfo deviceInfo;
52 private CONTEXT_STATE state;
53 private final RoleManager myManager;
55 RoleContextImpl(final DeviceInfo deviceInfo,
56 final HashedWheelTimer hashedWheelTimer,
57 final RoleManager myManager) {
58 this.deviceInfo = deviceInfo;
59 state = CONTEXT_STATE.WORKING;
60 this.myManager = myManager;
61 this.hashedWheelTimer = hashedWheelTimer;
66 public <T> RequestContext<T> createRequestContext() {
67 return new AbstractRequestContext<T>(deviceInfo.reserveXidForDeviceMessage()) {
75 public void setSalRoleService(@Nonnull final SalRoleService salRoleService) {
76 Preconditions.checkNotNull(salRoleService);
77 this.salRoleService = salRoleService;
81 public SalRoleService getSalRoleService() {
82 return this.salRoleService;
86 public CONTEXT_STATE getState() {
91 public void setState(CONTEXT_STATE state) {
96 public ServiceGroupIdentifier getServiceIdentifier() {
97 return this.deviceInfo.getServiceIdentifier();
101 public DeviceInfo getDeviceInfo() {
102 return this.deviceInfo;
105 public void startupClusterServices() throws ExecutionException, InterruptedException {
106 //TODO: Add callback ?
107 sendRoleChangeToDevice(OfpRole.BECOMEMASTER).get();
111 public ListenableFuture<Void> stopClusterServices() {
112 ListenableFuture<Void> future;
115 sendRoleChangeToDevice(OfpRole.BECOMESLAVE).get();
116 } catch (InterruptedException | ExecutionException e) {
117 LOG.warn("Send role to device failed ", e);
119 myManager.removeDeviceFromOperationalDS(deviceInfo, MAX_CLEAN_DS_RETRIES);
120 future = Futures.immediateFuture(null);
125 private ListenableFuture<RpcResult<SetRoleOutput>> sendRoleChangeToDevice(final OfpRole newRole) {
126 LOG.debug("Sending new role {} to device {}", newRole, deviceInfo.getNodeId());
127 final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
128 final Short version = deviceInfo.getVersion();
129 if (null == version) {
130 LOG.debug("Device version is null");
131 return Futures.immediateFuture(null);
133 if (version < OFConstants.OFP_VERSION_1_3) {
134 LOG.debug("Device version not support ROLE");
135 return Futures.immediateFuture(null);
137 final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
138 .setNode(new NodeRef(DeviceStateUtil.createNodeInstanceIdentifier(deviceInfo.getNodeId()))).build();
139 setRoleOutputFuture = getSalRoleService().setRole(setRoleInput);
140 final TimerTask timerTask = timeout -> {
141 if (!setRoleOutputFuture.isDone()) {
142 LOG.warn("New role {} was not propagated to device {} during 10 sec", newRole, deviceInfo.getNodeId());
143 setRoleOutputFuture.cancel(true);
146 hashedWheelTimer.newTimeout(timerTask, 10, TimeUnit.SECONDS);
148 return JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture);