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 static java.util.Objects.requireNonNull;
12 import akka.actor.ActorRef;
13 import akka.cluster.Cluster;
14 import akka.dispatch.OnComplete;
15 import akka.pattern.Patterns;
16 import akka.util.Timeout;
17 import com.google.common.annotations.VisibleForTesting;
18 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
19 import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
20 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
21 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
22 import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
23 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
24 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
25 import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
26 import org.opendaylight.netconf.topology.spi.NetconfClientConfigurationBuilderFactory;
27 import org.opendaylight.netconf.topology.spi.NetconfNodeHandler;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.optional.rev221225.NetconfNodeAugmentedOptional;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.NetconfNode;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 final class NetconfNodeContext implements AutoCloseable {
34 private static final Logger LOG = LoggerFactory.getLogger(NetconfNodeContext.class);
36 private final DeviceActionFactory deviceActionFactory;
37 private final SchemaResourceManager schemaManager;
38 private final NetconfClientConfigurationBuilderFactory builderFactory;
39 private final DOMMountPointService mountPointService;
40 private final RemoteDeviceId remoteDeviceId;
41 private final NetconfTopologySetup setup;
42 private final Timeout actorResponseWaitTime;
44 private ActorRef masterActorRef;
45 private MasterSalFacade masterSalFacade;
46 private NetconfNodeManager netconfNodeManager;
47 private NetconfNodeHandler nodeHandler;
49 NetconfNodeContext(final NetconfTopologySetup setup, final SchemaResourceManager schemaManager,
50 final DOMMountPointService mountPointService, final NetconfClientConfigurationBuilderFactory builderFactory,
51 final DeviceActionFactory deviceActionFactory, final RemoteDeviceId remoteDeviceId,
52 final Timeout actorResponseWaitTime) {
53 this.setup = requireNonNull(setup);
54 this.schemaManager = requireNonNull(schemaManager);
55 this.mountPointService = requireNonNull(mountPointService);
56 this.builderFactory = requireNonNull(builderFactory);
57 this.deviceActionFactory = deviceActionFactory;
58 this.remoteDeviceId = requireNonNull(remoteDeviceId);
59 this.actorResponseWaitTime = actorResponseWaitTime;
60 registerNodeManager();
63 void becomeTopologyLeader() {
64 // all nodes initially register listener
65 unregisterNodeManager();
67 // create master actor reference
68 final var masterAddress = Cluster.get(setup.getActorSystem()).selfAddress().toString();
69 masterActorRef = setup.getActorSystem().actorOf(NetconfNodeActor.props(setup, remoteDeviceId,
70 actorResponseWaitTime, mountPointService), NetconfTopologyUtils.createMasterActorName(
71 remoteDeviceId.name(), masterAddress));
76 void becomeTopologyFollower() {
77 registerNodeManager();
79 // disconnect device from this node and listen for changes from leader
82 if (masterActorRef != null) {
84 setup.getActorSystem().stop(masterActorRef);
88 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...");
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();
120 public void close() {
121 unregisterNodeManager();
123 // we expect that even leader node is going to be follower when data are deleted
124 // thus we do not close connection and actor here
125 // anyway we need to close topology and transaction chain on all nodes that were leaders
126 if (masterSalFacade != null) {
127 // node was at least once leader
128 masterSalFacade.close();
132 private void connectNode() {
133 final var configNode = setup.getNode();
135 final var netconfNode = configNode.augmentation(NetconfNode.class);
136 final var nodeOptional = configNode.augmentation(NetconfNodeAugmentedOptional.class);
138 requireNonNull(netconfNode.getHost());
139 requireNonNull(netconfNode.getPort());
141 // Instantiate the handler ...
142 masterSalFacade = createSalFacade(netconfNode.requireLockDatastore());
144 nodeHandler = new NetconfNodeHandler(setup.getNetconfClientFactory(), setup.getTimer(), setup.getBaseSchemas(),
145 schemaManager, setup.getProcessingExecutor(), builderFactory, deviceActionFactory, masterSalFacade,
146 remoteDeviceId, configNode.getNodeId(), netconfNode, nodeOptional);
147 nodeHandler.connect();
150 private void dropNode() {
151 if (nodeHandler != null) {
158 MasterSalFacade createSalFacade(final boolean lockDatastore) {
159 return new MasterSalFacade(remoteDeviceId, setup.getActorSystem(), masterActorRef, actorResponseWaitTime,
160 mountPointService, setup.getDataBroker(), lockDatastore);