2 * Copyright (c) 2016 Cisco Systems, Inc. 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 com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
13 import akka.actor.ActorRef;
14 import akka.cluster.Cluster;
15 import akka.dispatch.OnComplete;
16 import akka.pattern.Patterns;
17 import akka.util.Timeout;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import java.util.concurrent.atomic.AtomicBoolean;
20 import org.eclipse.jdt.annotation.NonNull;
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.sal.connect.api.DeviceActionFactory;
25 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceId;
26 import org.opendaylight.netconf.topology.singleton.api.RemoteDeviceConnector;
27 import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
28 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
29 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
30 import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
31 import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNode;
33 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 class NetconfTopologyContext implements ClusterSingletonService, AutoCloseable {
38 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyContext.class);
40 private final @NonNull ServiceGroupIdentifier serviceGroupIdent;
41 private final Timeout actorResponseWaitTime;
42 private final DOMMountPointService mountService;
43 private final DeviceActionFactory deviceActionFactory;
44 private final boolean lockDatastore;
46 private NetconfTopologySetup netconfTopologyDeviceSetup;
47 private RemoteDeviceId remoteDeviceId;
48 private RemoteDeviceConnector remoteDeviceConnector;
49 private NetconfNodeManager netconfNodeManager;
50 private ActorRef masterActorRef;
52 private final AtomicBoolean closed = new AtomicBoolean(false);
53 private final AtomicBoolean stopped = new AtomicBoolean(false);
54 private volatile boolean isMaster;
56 NetconfTopologyContext(final NetconfTopologySetup netconfTopologyDeviceSetup,
57 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
58 final DOMMountPointService mountService, final DeviceActionFactory deviceActionFactory) {
59 this.netconfTopologyDeviceSetup = requireNonNull(netconfTopologyDeviceSetup);
60 this.serviceGroupIdent = requireNonNull(serviceGroupIdent);
61 this.actorResponseWaitTime = actorResponseWaitTime;
62 this.mountService = mountService;
63 this.deviceActionFactory = deviceActionFactory;
65 final var node = netconfTopologyDeviceSetup.getNode();
66 final var netconfNode = verifyNotNull(node.augmentation(NetconfNode.class));
67 remoteDeviceId = NetconfNodeUtils.toRemoteDeviceId(node.getNodeId(), netconfNode);
68 remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId,
70 netconfNodeManager = createNodeDeviceManager();
71 lockDatastore = netconfNode.requireLockDatastore();
75 public void instantiateServiceInstance() {
76 LOG.info("Master was selected: {}", remoteDeviceId.host().getIpAddress());
80 // master should not listen on netconf-node operational datastore
81 if (netconfNodeManager != null) {
82 netconfNodeManager.close();
83 netconfNodeManager = null;
87 final String masterAddress =
88 Cluster.get(netconfTopologyDeviceSetup.getActorSystem()).selfAddress().toString();
89 masterActorRef = netconfTopologyDeviceSetup.getActorSystem().actorOf(NetconfNodeActor.props(
90 netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService),
91 NetconfTopologyUtils.createMasterActorName(remoteDeviceId.name(), masterAddress));
93 remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
98 // called when master is down/changed to slave
100 public ListenableFuture<?> closeServiceInstance() {
103 // in case that master changes role to slave, new NodeDeviceManager must be created and listener registered
104 netconfNodeManager = createNodeDeviceManager();
106 stopDeviceConnectorAndActor();
108 return FluentFutures.immediateNullFluentFuture();
112 public ServiceGroupIdentifier getIdentifier() {
113 return serviceGroupIdent;
116 private NetconfNodeManager createNodeDeviceManager() {
117 final NetconfNodeManager ndm =
118 new NetconfNodeManager(netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService);
119 ndm.registerDataTreeChangeListener(netconfTopologyDeviceSetup.getTopologyId(),
120 netconfTopologyDeviceSetup.getNode().key());
126 public void close() {
127 if (!closed.compareAndSet(false, true)) {
131 if (netconfNodeManager != null) {
132 netconfNodeManager.close();
134 stopDeviceConnectorAndActor();
139 * Refresh, if configuration data was changed.
140 * @param setup new setup
142 void refresh(final @NonNull NetconfTopologySetup setup) {
143 netconfTopologyDeviceSetup = requireNonNull(setup);
144 final var node = netconfTopologyDeviceSetup.getNode();
145 remoteDeviceId = NetconfNodeUtils.toRemoteDeviceId(node.getNodeId(), node.augmentation(NetconfNode.class));
148 remoteDeviceConnector.stopRemoteDeviceConnection();
150 netconfNodeManager.refreshDevice(netconfTopologyDeviceSetup, remoteDeviceId);
152 remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId,
153 deviceActionFactory);
156 Patterns.ask(masterActorRef, new RefreshSetupMasterActorData(netconfTopologyDeviceSetup, remoteDeviceId),
157 actorResponseWaitTime).onComplete(new OnComplete<>() {
159 public void onComplete(final Throwable failure, final Object success) {
160 if (failure != null) {
161 LOG.error("Failed to refresh master actor data", failure);
164 remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
166 }, netconfTopologyDeviceSetup.getActorSystem().dispatcher());
170 private void stopDeviceConnectorAndActor() {
171 if (!stopped.compareAndSet(false, true)) {
174 if (remoteDeviceConnector != null) {
175 remoteDeviceConnector.stopRemoteDeviceConnection();
178 if (masterActorRef != null) {
179 netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
180 masterActorRef = null;
184 protected MasterSalFacade newMasterSalFacade() {
185 return new MasterSalFacade(remoteDeviceId, netconfTopologyDeviceSetup.getActorSystem(), masterActorRef,
186 actorResponseWaitTime, mountService, netconfTopologyDeviceSetup.getDataBroker(), lockDatastore);