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 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.util.concurrent.ListenableFuture;
18 import java.util.concurrent.atomic.AtomicBoolean;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
21 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
22 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
23 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
24 import org.opendaylight.netconf.topology.singleton.api.RemoteDeviceConnector;
25 import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
26 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
27 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
28 import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
30 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import scala.concurrent.Future;
35 class NetconfTopologyContext implements ClusterSingletonService, AutoCloseable {
37 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyContext.class);
39 private final ServiceGroupIdentifier serviceGroupIdent;
40 private final Timeout actorResponseWaitTime;
41 private final DOMMountPointService mountService;
43 private NetconfTopologySetup netconfTopologyDeviceSetup;
44 private RemoteDeviceId remoteDeviceId;
45 private RemoteDeviceConnector remoteDeviceConnector;
46 private NetconfNodeManager netconfNodeManager;
47 private ActorRef masterActorRef;
48 private final AtomicBoolean closed = new AtomicBoolean(false);
49 private final AtomicBoolean stopped = new AtomicBoolean(false);
50 private volatile boolean isMaster;
52 NetconfTopologyContext(final NetconfTopologySetup netconfTopologyDeviceSetup,
53 final ServiceGroupIdentifier serviceGroupIdent,
54 final Timeout actorResponseWaitTime, final DOMMountPointService mountService) {
55 this.netconfTopologyDeviceSetup = requireNonNull(netconfTopologyDeviceSetup);
56 this.serviceGroupIdent = serviceGroupIdent;
57 this.actorResponseWaitTime = actorResponseWaitTime;
58 this.mountService = mountService;
60 remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
61 netconfTopologyDeviceSetup.getNode().augmentation(NetconfNode.class));
63 remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
65 netconfNodeManager = createNodeDeviceManager();
69 public void instantiateServiceInstance() {
70 LOG.info("Master was selected: {}", remoteDeviceId.getHost().getIpAddress());
74 // master should not listen on netconf-node operational datastore
75 if (netconfNodeManager != null) {
76 netconfNodeManager.close();
77 netconfNodeManager = null;
81 final String masterAddress =
82 Cluster.get(netconfTopologyDeviceSetup.getActorSystem()).selfAddress().toString();
83 masterActorRef = netconfTopologyDeviceSetup.getActorSystem().actorOf(NetconfNodeActor.props(
84 netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService),
85 NetconfTopologyUtils.createMasterActorName(remoteDeviceId.getName(), masterAddress));
87 remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
92 // called when master is down/changed to slave
94 public ListenableFuture<?> closeServiceInstance() {
97 // in case that master changes role to slave, new NodeDeviceManager must be created and listener registered
98 netconfNodeManager = createNodeDeviceManager();
100 stopDeviceConnectorAndActor();
102 return FluentFutures.immediateNullFluentFuture();
106 public ServiceGroupIdentifier getIdentifier() {
107 return serviceGroupIdent;
110 private NetconfNodeManager createNodeDeviceManager() {
111 final NetconfNodeManager ndm =
112 new NetconfNodeManager(netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService);
113 ndm.registerDataTreeChangeListener(netconfTopologyDeviceSetup.getTopologyId(),
114 netconfTopologyDeviceSetup.getNode().key());
120 public void close() {
121 if (!closed.compareAndSet(false, true)) {
125 if (netconfNodeManager != null) {
126 netconfNodeManager.close();
128 stopDeviceConnectorAndActor();
133 * Refresh, if configuration data was changed.
134 * @param setup new setup
136 void refresh(final @NonNull NetconfTopologySetup setup) {
137 netconfTopologyDeviceSetup = requireNonNull(setup);
138 remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
139 netconfTopologyDeviceSetup.getNode().augmentation(NetconfNode.class));
142 remoteDeviceConnector.stopRemoteDeviceConnection();
145 netconfNodeManager.refreshDevice(netconfTopologyDeviceSetup, remoteDeviceId);
147 remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
150 final Future<Object> future = Patterns.ask(masterActorRef, new RefreshSetupMasterActorData(
151 netconfTopologyDeviceSetup, remoteDeviceId), actorResponseWaitTime);
153 future.onComplete(new OnComplete<Object>() {
155 public void onComplete(final Throwable failure, final Object success) {
156 if (failure != null) {
157 LOG.error("Failed to refresh master actor data", failure);
160 remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
162 }, netconfTopologyDeviceSetup.getActorSystem().dispatcher());
166 private void stopDeviceConnectorAndActor() {
167 if (!stopped.compareAndSet(false, true)) {
170 if (remoteDeviceConnector != null) {
171 remoteDeviceConnector.stopRemoteDeviceConnection();
174 if (masterActorRef != null) {
175 netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
176 masterActorRef = null;
180 protected MasterSalFacade newMasterSalFacade() {
181 return new MasterSalFacade(remoteDeviceId, netconfTopologyDeviceSetup.getActorSystem(), masterActorRef,
182 actorResponseWaitTime, mountService, netconfTopologyDeviceSetup.getDataBroker());