Merge "Report (TCP) port number for switches"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / lifecycle / LifecycleServiceImpl.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.MoreObjects;
11 import com.google.common.base.Verify;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Objects;
18 import java.util.concurrent.ExecutorService;
19 import javax.annotation.Nonnull;
20 import javax.annotation.Nullable;
21 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
22 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
23 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
24 import org.opendaylight.openflowplugin.api.openflow.OFPContext.ContextState;
25 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
26 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
27 import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler;
28 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceRemovedHandler;
29 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
30 import org.opendaylight.openflowplugin.api.openflow.lifecycle.MastershipChangeListener;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
32 import org.opendaylight.yangtools.yang.common.RpcResult;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 public class LifecycleServiceImpl implements LifecycleService {
37
38     private static final Logger LOG = LoggerFactory.getLogger(LifecycleServiceImpl.class);
39
40     private final List<DeviceRemovedHandler> deviceRemovedHandlers = new ArrayList<>();
41     private final MastershipChangeListener mastershipChangeListener;
42     private final ExecutorService executorService;
43     private ClusterSingletonServiceRegistration registration;
44     private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler;
45     private ServiceGroupIdentifier serviceGroupIdentifier;
46     private DeviceInfo deviceInfo;
47     private volatile ContextState state = ContextState.INITIALIZATION;
48
49     public LifecycleServiceImpl(@Nonnull final MastershipChangeListener mastershipChangeListener,
50                                 @Nonnull final ExecutorService executorService) {
51         this.mastershipChangeListener = mastershipChangeListener;
52         this.executorService = executorService;
53     }
54
55     @Override
56     public void makeDeviceSlave(final DeviceContext deviceContext) {
57         deviceInfo = MoreObjects.firstNonNull(deviceInfo, deviceContext.getDeviceInfo());
58
59         Futures.addCallback(deviceContext.makeDeviceSlave(), new FutureCallback<RpcResult<SetRoleOutput>>() {
60             @Override
61             public void onSuccess(@Nullable RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
62                 if (LOG.isDebugEnabled()) {
63                     LOG.debug("Role SLAVE was successfully propagated on device, node {}",
64                             deviceContext.getDeviceInfo().getLOGValue());
65                 }
66                 mastershipChangeListener.onSlaveRoleAcquired(deviceInfo);
67             }
68
69             @Override
70             public void onFailure(@Nonnull Throwable throwable) {
71                 LOG.warn("Was not able to set role SLAVE to device on node {} ",
72                         deviceContext.getDeviceInfo().getLOGValue());
73                 mastershipChangeListener.onSlaveRoleNotAcquired(deviceInfo);
74             }
75         });
76     }
77
78     @Override
79     public void instantiateServiceInstance() {
80         executorService.submit(() -> {
81             LOG.info("Starting clustering services for node {}", deviceInfo.getLOGValue());
82
83             if (!clusterInitializationPhaseHandler.onContextInstantiateService(mastershipChangeListener)) {
84                 mastershipChangeListener.onNotAbleToStartMastershipMandatory(deviceInfo, "Cannot initialize device.");
85             }
86         });
87     }
88
89     @Override
90     public ListenableFuture<Void> closeServiceInstance() {
91         LOG.info("Closing clustering services for node {}", deviceInfo.getLOGValue());
92         return Futures.immediateFuture(null);
93     }
94
95     @Override
96     @Nonnull
97     public ServiceGroupIdentifier getIdentifier() {
98         return this.serviceGroupIdentifier;
99     }
100
101     @Override
102     public void close() {
103         if (ContextState.TERMINATION.equals(state)) {
104             if (LOG.isDebugEnabled()) {
105                 LOG.debug("LifecycleService for node {} is already in TERMINATION state.", deviceInfo.getLOGValue());
106             }
107         } else {
108             state = ContextState.TERMINATION;
109
110             // We are closing, so cleanup all managers now
111             deviceRemovedHandlers.forEach(h -> h.onDeviceRemoved(deviceInfo));
112
113             // If we are still registered and we are not already closing, then close the registration
114             if (Objects.nonNull(registration)) {
115                 try {
116                     LOG.info("Closing clustering services registration for node {}", deviceInfo.getLOGValue());
117                     registration.close();
118                     registration = null;
119                 } catch (final Exception e) {
120                     LOG.warn("Failed to close clustering services registration for node {} with exception: ",
121                             deviceInfo.getLOGValue(), e);
122                 }
123             }
124         }
125     }
126
127     @Override
128     public void registerService(@Nonnull final ClusterSingletonServiceProvider singletonServiceProvider,
129                                 @Nonnull final DeviceContext deviceContext) {
130         Verify.verify(Objects.isNull(registration));
131         this.clusterInitializationPhaseHandler = deviceContext;
132         this.serviceGroupIdentifier = deviceContext.getServiceIdentifier();
133         this.deviceInfo = deviceContext.getDeviceInfo();
134         this.registration = Verify.verifyNotNull(
135                 singletonServiceProvider.registerClusterSingletonService(this));
136
137         LOG.info("Registered clustering services for node {}", deviceInfo.getLOGValue());
138     }
139
140     @Override
141     public void registerDeviceRemovedHandler(@Nonnull final DeviceRemovedHandler deviceRemovedHandler) {
142         if (!deviceRemovedHandlers.contains(deviceRemovedHandler)) {
143             deviceRemovedHandlers.add(deviceRemovedHandler);
144         }
145     }
146
147 }