91f4ecf4056f5b2d528c1f4b358bcb30cf8ea2d6
[netconf.git] / apps / netconf-topology-singleton / src / main / java / org / opendaylight / netconf / topology / singleton / impl / NetconfTopologyContext.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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.netconf.topology.singleton.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import akka.util.Timeout;
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import io.netty.util.concurrent.EventExecutor;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
18 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
19 import org.opendaylight.controller.config.threadpool.ThreadPool;
20 import org.opendaylight.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
22 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
23 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
24 import org.opendaylight.netconf.client.NetconfClientDispatcher;
25 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
26 import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
27 import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
28 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
29 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
30 import org.opendaylight.netconf.client.mdsal.api.SslHandlerFactoryProvider;
31 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
32 import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNode;
34 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 class NetconfTopologyContext implements ClusterSingletonService, AutoCloseable {
39     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyContext.class);
40
41     private final @NonNull ServiceGroupIdentifier serviceGroupIdent;
42     private final NetconfTopologySingletonImpl topologySingleton;
43
44     private volatile boolean closed;
45     private volatile boolean isMaster;
46
47     private RemoteDeviceId remoteDeviceId;
48
49     NetconfTopologyContext(final String topologyId, final NetconfClientDispatcher clientDispatcher,
50             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
51             final ThreadPool processingExecutor, final SchemaResourceManager schemaManager,
52             final DataBroker dataBroker, final DOMMountPointService mountPointService,
53             final AAAEncryptionService encryptionService, final DeviceActionFactory deviceActionFactory,
54             final BaseNetconfSchemas baseSchemas, final Timeout actorResponseWaitTime,
55             final ServiceGroupIdentifier serviceGroupIdent, final NetconfTopologySetup setup,
56             final CredentialProvider credentialProvider, final SslHandlerFactoryProvider sslHandlerFactoryProvider) {
57         this.serviceGroupIdent = requireNonNull(serviceGroupIdent);
58         this.remoteDeviceId = NetconfNodeUtils.toRemoteDeviceId(setup.getNode().getNodeId(),
59                 setup.getNode().augmentation(NetconfNode.class));
60
61         this.topologySingleton = new NetconfTopologySingletonImpl(topologyId, clientDispatcher,
62                 eventExecutor, keepaliveExecutor, processingExecutor, schemaManager, dataBroker, mountPointService,
63                 encryptionService, deviceActionFactory, baseSchemas, remoteDeviceId, setup, actorResponseWaitTime,
64                 credentialProvider, sslHandlerFactoryProvider);
65     }
66
67     @VisibleForTesting
68     protected NetconfTopologySingletonImpl getTopologySingleton() {
69         // FIXME we have to access topology singleton via this method because of mocking in MountPointEndToEndTest
70         return topologySingleton;
71     }
72
73     @Override
74     public void instantiateServiceInstance() {
75         LOG.info("Leader was selected: {}", remoteDeviceId.host().getIpAddress());
76         if (closed) {
77             LOG.warn("Instance is already closed.");
78             return;
79         }
80         isMaster = true;
81         getTopologySingleton().becomeTopologyLeader();
82     }
83
84     // called when master is down/changed to slave
85     @Override
86     public ListenableFuture<?> closeServiceInstance() {
87         // this method is also called when topology data are deleted
88         LOG.info("Follower was selected: {}", remoteDeviceId.host().getIpAddress());
89         if (closed) {
90             LOG.warn("Instance is already closed.");
91             return FluentFutures.immediateNullFluentFuture();
92         }
93         getTopologySingleton().becomeTopologyFollower();
94         return FluentFutures.immediateNullFluentFuture();
95     }
96
97     void refresh(final @NonNull NetconfTopologySetup setup) {
98         final var node = requireNonNull(setup).getNode();
99         remoteDeviceId = NetconfNodeUtils.toRemoteDeviceId(node.getNodeId(), node.augmentation(NetconfNode.class));
100
101         if (isMaster) {
102             getTopologySingleton().disconnectNode(setup.getNode().getNodeId());
103             getTopologySingleton().refreshSetupConnection(setup, remoteDeviceId);
104         } else {
105             getTopologySingleton().refreshDevice(setup, remoteDeviceId);
106         }
107     }
108
109     @Override
110     public ServiceGroupIdentifier getIdentifier() {
111         return serviceGroupIdent;
112     }
113
114     @Override
115     public void close() {
116         if (closed) {
117             LOG.warn("Instance is already closed.");
118             return;
119         }
120         getTopologySingleton().close();
121         closed = true;
122     }
123 }