2 * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.netconf.topology.singleton.impl;
10 import akka.actor.ActorRef;
11 import akka.cluster.Cluster;
12 import akka.dispatch.OnComplete;
13 import akka.pattern.Patterns;
14 import akka.util.Timeout;
15 import io.netty.util.concurrent.EventExecutor;
16 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
17 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
18 import org.opendaylight.controller.config.threadpool.ThreadPool;
19 import org.opendaylight.mdsal.binding.api.DataBroker;
20 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
21 import org.opendaylight.netconf.client.NetconfClientDispatcher;
22 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
23 import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
24 import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
25 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceHandler;
26 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
27 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
28 import org.opendaylight.netconf.client.mdsal.api.SslHandlerFactoryProvider;
29 import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
30 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
31 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
32 import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
33 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 final class NetconfTopologySingletonImpl extends AbstractNetconfTopology implements AutoCloseable {
39 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologySingletonImpl.class);
41 private final RemoteDeviceId remoteDeviceId;
42 private final NetconfTopologySetup setup;
43 private final Timeout actorResponseWaitTime;
45 private ActorRef masterActorRef;
46 private MasterSalFacade masterSalFacade;
47 private NetconfNodeManager netconfNodeManager;
49 NetconfTopologySingletonImpl(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 RemoteDeviceId remoteDeviceId,
55 final NetconfTopologySetup setup, final Timeout actorResponseWaitTime,
56 final CredentialProvider credentialProvider, final SslHandlerFactoryProvider sslHandlerFactoryProvider) {
57 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor, schemaManager,
58 dataBroker, mountPointService, encryptionService, deviceActionFactory, baseSchemas, credentialProvider,
59 sslHandlerFactoryProvider);
60 this.remoteDeviceId = remoteDeviceId;
62 this.actorResponseWaitTime = actorResponseWaitTime;
63 registerNodeManager();
66 void becomeTopologyLeader() {
67 // all nodes initially register listener
68 unregisterNodeManager();
70 // create master actor reference
71 final var masterAddress = Cluster.get(setup.getActorSystem()).selfAddress().toString();
72 masterActorRef = setup.getActorSystem().actorOf(NetconfNodeActor.props(setup, remoteDeviceId,
73 actorResponseWaitTime, mountPointService), NetconfTopologyUtils.createMasterActorName(
74 remoteDeviceId.name(), masterAddress));
76 // setup connection to device
77 ensureNode(setup.getNode());
80 void becomeTopologyFollower() {
81 registerNodeManager();
82 // disconnect device from this node and listen for changes from leader
83 deleteNode(setup.getNode().getNodeId());
84 if (masterActorRef != null) {
86 setup.getActorSystem().stop(masterActorRef);
90 void refreshSetupConnection(final NetconfTopologySetup netconfTopologyDeviceSetup, final RemoteDeviceId device) {
91 Patterns.ask(masterActorRef, new RefreshSetupMasterActorData(netconfTopologyDeviceSetup, device),
92 actorResponseWaitTime).onComplete(
95 public void onComplete(final Throwable failure, final Object success) {
96 if (failure != null) {
97 LOG.error("Failed to refresh master actor data", failure);
100 LOG.debug("Succeed to refresh Master Action data. Creating Connector...");
101 setupConnection(setup.getNode().getNodeId(), setup.getNode());
103 }, netconfTopologyDeviceSetup.getActorSystem().dispatcher());
106 void refreshDevice(final NetconfTopologySetup netconfTopologyDeviceSetup, final RemoteDeviceId deviceId) {
107 netconfNodeManager.refreshDevice(netconfTopologyDeviceSetup, deviceId);
110 private void registerNodeManager() {
111 netconfNodeManager = new NetconfNodeManager(setup, remoteDeviceId, actorResponseWaitTime, mountPointService);
112 netconfNodeManager.registerDataTreeChangeListener(setup.getTopologyId(), setup.getNode().key());
115 private void unregisterNodeManager() {
116 netconfNodeManager.close();
119 void dropNode(final NodeId nodeId) {
124 public void close() {
125 unregisterNodeManager();
127 // we expect that even leader node is going to be follower when data are deleted
128 // thus we do not close connection and actor here
129 // anyway we need to close topology and transaction chain on all nodes that were leaders
130 if (masterSalFacade != null) {
131 // node was at least once leader
132 masterSalFacade.close();
137 public RemoteDeviceHandler createSalFacade(final RemoteDeviceId deviceId, final boolean lockDatastore) {
138 masterSalFacade = new MasterSalFacade(deviceId, setup.getActorSystem(), masterActorRef,
139 actorResponseWaitTime, mountPointService, dataBroker, lockDatastore);
140 return masterSalFacade;