8fe1a89dd0809930011f6bd29a9040c8a9db7ea2
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / lifecycle / ContextChainHolderImpl.java
1 /*
2  * Copyright (c) 2016 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.openflowplugin.impl.lifecycle;
9
10 import com.google.common.base.Verify;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.Objects;
15 import java.util.concurrent.ConcurrentHashMap;
16 import javax.annotation.Nonnull;
17 import javax.annotation.Nullable;
18 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
19 import org.opendaylight.openflowplugin.api.openflow.OFPManager;
20 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
21 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionStatus;
22 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
23 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
24 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
25 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChain;
26 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainHolder;
27 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
28 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
29 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
30 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
31 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.ContextChainState;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.openflow.provider.config.ContextChainConfig;
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;
38
39 public class ContextChainHolderImpl implements ContextChainHolder {
40
41     private static final Logger LOG = LoggerFactory.getLogger(ContextChainHolderImpl.class);
42     private static final String NOT_ALL_MANAGER_WERE_SET = "Not all manager were set.";
43     private static final String MANAGER_WAS_SET = " manager was set";
44     private static final String CONTEXT_CREATED_FOR_CONNECTION = " context created for connection: {}";
45     private static final String SINGLETON_SERVICE_PROVIDER_WAS_NOT_SET_YET
46             = "Singleton service provider was not set yet.";
47
48     private DeviceManager deviceManager;
49     private RpcManager rpcManager;
50     private StatisticsManager statisticsManager;
51     private ConcurrentHashMap<DeviceInfo, ContextChain> contextChainMap = new ConcurrentHashMap<>();
52     private ConcurrentHashMap<DeviceInfo, ConnectionContext> latestConnections = new ConcurrentHashMap<>();
53     private final ContextChainConfig config;
54     private ClusterSingletonServiceProvider singletonServicesProvider;
55
56     public ContextChainHolderImpl(final ContextChainConfig config) {
57         this.config = config;
58     }
59
60     @Override
61     public <T extends OFPManager> void addManager(final T manager) {
62         if (Objects.isNull(deviceManager) && manager instanceof DeviceManager) {
63             LOG.info("Device" + MANAGER_WAS_SET);
64             deviceManager = (DeviceManager) manager;
65         } else if (Objects.isNull(rpcManager) && manager instanceof RpcManager) {
66             LOG.info("RPC" + MANAGER_WAS_SET);
67             rpcManager = (RpcManager) manager;
68         } else if (Objects.isNull(statisticsManager) && manager instanceof StatisticsManager) {
69             LOG.info("Statistics" + MANAGER_WAS_SET);
70             statisticsManager = (StatisticsManager) manager;
71         }
72     }
73
74     @Override
75     public ContextChain createContextChain(final ConnectionContext connectionContext) {
76
77         final DeviceInfo deviceInfo = connectionContext.getDeviceInfo();
78         final String deviceInfoLOGValue = deviceInfo.getLOGValue();
79
80         if (LOG.isDebugEnabled()) {
81             LOG.debug("Creating a new chain" + CONTEXT_CREATED_FOR_CONNECTION, deviceInfoLOGValue);
82         }
83
84         ContextChain contextChain = new ContextChainImpl();
85         LifecycleService lifecycleService = new LifecycleServiceImpl(this);
86
87         if (LOG.isDebugEnabled()) {
88             LOG.debug("Lifecycle services" + CONTEXT_CREATED_FOR_CONNECTION, deviceInfoLOGValue);
89         }
90
91         final DeviceContext deviceContext = deviceManager.createContext(connectionContext);
92
93         if (LOG.isDebugEnabled()) {
94             LOG.debug("Device" + CONTEXT_CREATED_FOR_CONNECTION, deviceInfoLOGValue);
95         }
96
97         final RpcContext rpcContext = rpcManager.createContext(connectionContext.getDeviceInfo(), deviceContext);
98
99         if (LOG.isDebugEnabled()) {
100             LOG.debug("RPC" + CONTEXT_CREATED_FOR_CONNECTION, deviceInfoLOGValue);
101         }
102
103         final StatisticsContext statisticsContext
104                 = statisticsManager.createContext(deviceContext);
105
106         if (LOG.isDebugEnabled()) {
107             LOG.debug("Statistics" + CONTEXT_CREATED_FOR_CONNECTION, deviceInfoLOGValue);
108         }
109
110         deviceContext.setLifecycleInitializationPhaseHandler(statisticsContext);
111         statisticsContext.setLifecycleInitializationPhaseHandler(rpcContext);
112         statisticsContext.setInitialSubmitHandler(deviceContext);
113
114         contextChain.addLifecycleService(lifecycleService);
115         contextChain.addContext(deviceContext);
116         contextChain.addContext(rpcContext);
117         contextChain.addContext(statisticsContext);
118         contextChain.makeDeviceSlave();
119
120         return contextChain;
121
122     }
123
124     @Override
125     public ListenableFuture<Void> connectionLost(final DeviceInfo deviceInfo) {
126         if (!this.checkChainContext(deviceInfo)) {
127             return Futures.immediateFuture(null);
128         }
129         return null;
130     }
131
132     @Override
133     public void destroyContextChain(final DeviceInfo deviceInfo) {
134         ContextChain chain = contextChainMap.get(deviceInfo);
135         if (Objects.nonNull(chain)) {
136             chain.close();
137         }
138     }
139
140     @Override
141     public void pairConnection(final ConnectionContext connectionContext) {
142         DeviceInfo deviceInfo = connectionContext.getDeviceInfo();
143         latestConnections.put(deviceInfo, connectionContext);
144         if (checkChainContext(deviceInfo)) {
145             contextChainMap.get(deviceInfo).changePrimaryConnection(connectionContext);
146         }
147     }
148
149     @Override
150     public ConnectionStatus deviceConnected(final ConnectionContext connectionContext) throws Exception {
151
152         Verify.verify(this.checkAllManagers(), NOT_ALL_MANAGER_WERE_SET);
153         Verify.verifyNotNull(this.singletonServicesProvider, SINGLETON_SERVICE_PROVIDER_WAS_NOT_SET_YET);
154
155         LOG.info("Device {} connected.", connectionContext.getDeviceInfo().getLOGValue());
156         ContextChain chain = contextChainMap.get(connectionContext.getDeviceInfo());
157
158         if (Objects.isNull(chain)) {
159             contextChainMap.put(connectionContext.getDeviceInfo(), createContextChain(connectionContext));
160         } else {
161             this.pairConnection(connectionContext);
162         }
163
164         return ConnectionStatus.MAY_CONTINUE;
165     }
166
167     @Override
168     public void addSingletonServicesProvider(final ClusterSingletonServiceProvider singletonServicesProvider) {
169         this.singletonServicesProvider = singletonServicesProvider;
170     }
171
172     @Override
173     public void onNotAbleToStartMastership(final DeviceInfo deviceInfo) {
174         ContextChain contextChain = contextChainMap.get(deviceInfo);
175         if (Objects.nonNull(contextChain)) {
176             LOG.warn("Not able to set MASTER role on device {}", deviceInfo.getLOGValue());
177             if (contextChain.getContextChainState().equals(ContextChainState.INITIALIZED)) {
178                 contextChain.getPrimaryConnectionContext().closeConnection(false);
179             } else {
180                 contextChain.sleepTheChainAndDropConnection();
181             }
182         }
183     }
184
185     @Override
186     public void onMasterRoleAcquired(final DeviceInfo deviceInfo) {
187         ContextChain contextChain = contextChainMap.get(deviceInfo);
188         if (Objects.nonNull(contextChain)) {
189             if (contextChain.getContextChainState().equals(ContextChainState.WORKINGMASTER)) {
190                 if (LOG.isDebugEnabled()) {
191                     LOG.debug("Device {} already working as MASTER no changes need to be done.",
192                             deviceInfo.getLOGValue());
193                 }
194             } else {
195                 if (contextChain.getContextChainState().equals(ContextChainState.INITIALIZED)) {
196                     LOG.info("Device {} has not finish initial gathering yet.",
197                             deviceInfo.getLOGValue());
198                 }
199                 contextChain.startChain();
200             }
201         }
202     }
203
204     @Override
205     public void onSlaveRoleAcquired(final DeviceInfo deviceInfo) {
206         ContextChain contextChain = contextChainMap.get(deviceInfo);
207         if (Objects.nonNull(contextChain)) {
208             if (contextChain.getContextChainState().equals(ContextChainState.INITIALIZED)) {
209                 contextChain.registerServices(this.singletonServicesProvider);
210             } else {
211                 contextChain.stopChain();
212             }
213         }
214     }
215
216     @Override
217     public void onSlaveRoleNotAcquired(final DeviceInfo deviceInfo) {
218         ContextChain contextChain = contextChainMap.get(deviceInfo);
219         if (Objects.nonNull(contextChain)) {
220             contextChain.sleepTheChainAndDropConnection();
221         }
222     }
223
224     private boolean checkAllManagers() {
225         return Objects.nonNull(deviceManager) && Objects.nonNull(rpcManager) && Objects.nonNull(statisticsManager);
226     }
227
228     private boolean checkChainContext(final DeviceInfo deviceInfo) {
229         return contextChainMap.containsKey(deviceInfo);
230     }
231
232 }