Custom scheme-cache-directory yang models are not replicated among
[netconf.git] / netconf / 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 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 com.google.common.base.Preconditions;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.util.concurrent.atomic.AtomicBoolean;
19 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
20 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
21 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
22 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
23 import org.opendaylight.netconf.topology.singleton.api.RemoteDeviceConnector;
24 import org.opendaylight.netconf.topology.singleton.impl.actors.NetconfNodeActor;
25 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
26 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
27 import org.opendaylight.netconf.topology.singleton.messages.RefreshSetupMasterActorData;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import scala.concurrent.Future;
32
33 class NetconfTopologyContext implements ClusterSingletonService, AutoCloseable {
34
35     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyContext.class);
36
37     private final ServiceGroupIdentifier serviceGroupIdent;
38     private final Timeout actorResponseWaitTime;
39     private final DOMMountPointService mountService;
40
41     private NetconfTopologySetup netconfTopologyDeviceSetup;
42     private RemoteDeviceId remoteDeviceId;
43     private RemoteDeviceConnector remoteDeviceConnector;
44     private NetconfNodeManager netconfNodeManager;
45     private ActorRef masterActorRef;
46     private final AtomicBoolean closed = new AtomicBoolean(false);
47     private final AtomicBoolean stopped = new AtomicBoolean(false);
48     private volatile boolean isMaster;
49
50     NetconfTopologyContext(final NetconfTopologySetup netconfTopologyDeviceSetup,
51                            final ServiceGroupIdentifier serviceGroupIdent,
52                            final Timeout actorResponseWaitTime, final DOMMountPointService mountService) {
53         this.netconfTopologyDeviceSetup = Preconditions.checkNotNull(netconfTopologyDeviceSetup);
54         this.serviceGroupIdent = serviceGroupIdent;
55         this.actorResponseWaitTime = actorResponseWaitTime;
56         this.mountService = mountService;
57
58         remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
59                 netconfTopologyDeviceSetup.getNode().augmentation(NetconfNode.class));
60
61         remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
62
63         netconfNodeManager = createNodeDeviceManager();
64     }
65
66     @Override
67     public void instantiateServiceInstance() {
68         LOG.info("Master was selected: {}", remoteDeviceId.getHost().getIpAddress());
69
70         isMaster = true;
71
72         // master should not listen on netconf-node operational datastore
73         if (netconfNodeManager != null) {
74             netconfNodeManager.close();
75             netconfNodeManager = null;
76         }
77
78         if (!closed.get()) {
79             final String masterAddress =
80                     Cluster.get(netconfTopologyDeviceSetup.getActorSystem()).selfAddress().toString();
81             masterActorRef = netconfTopologyDeviceSetup.getActorSystem().actorOf(NetconfNodeActor.props(
82                     netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService),
83                     NetconfTopologyUtils.createMasterActorName(remoteDeviceId.getName(), masterAddress));
84
85             remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
86         }
87
88     }
89
90     // called when master is down/changed to slave
91     @Override
92     public ListenableFuture<Void> closeServiceInstance() {
93
94         if (!closed.get()) {
95             // in case that master changes role to slave, new NodeDeviceManager must be created and listener registered
96             netconfNodeManager = createNodeDeviceManager();
97         }
98         stopDeviceConnectorAndActor();
99
100         return Futures.immediateFuture(null);
101     }
102
103     @Override
104     public ServiceGroupIdentifier getIdentifier() {
105         return serviceGroupIdent;
106     }
107
108     private NetconfNodeManager createNodeDeviceManager() {
109         final NetconfNodeManager ndm =
110                 new NetconfNodeManager(netconfTopologyDeviceSetup, remoteDeviceId, actorResponseWaitTime, mountService);
111         ndm.registerDataTreeChangeListener(netconfTopologyDeviceSetup.getTopologyId(),
112                 netconfTopologyDeviceSetup.getNode().key());
113
114         return ndm;
115     }
116
117     @Override
118     public void close() {
119         if (!closed.compareAndSet(false, true)) {
120             return;
121         }
122
123         if (netconfNodeManager != null) {
124             netconfNodeManager.close();
125         }
126         stopDeviceConnectorAndActor();
127
128     }
129
130     /**
131      * Refresh, if configuration data was changed.
132      * @param setup new setup
133      */
134     void refresh(final NetconfTopologySetup setup) {
135         netconfTopologyDeviceSetup = Preconditions.checkNotNull(setup);
136         remoteDeviceId = NetconfTopologyUtils.createRemoteDeviceId(netconfTopologyDeviceSetup.getNode().getNodeId(),
137                 netconfTopologyDeviceSetup.getNode().augmentation(NetconfNode.class));
138
139         if (isMaster) {
140             remoteDeviceConnector.stopRemoteDeviceConnection();
141         }
142         if (!isMaster) {
143             netconfNodeManager.refreshDevice(netconfTopologyDeviceSetup, remoteDeviceId);
144         }
145         remoteDeviceConnector = new RemoteDeviceConnectorImpl(netconfTopologyDeviceSetup, remoteDeviceId);
146
147         if (isMaster) {
148             final Future<Object> future = Patterns.ask(masterActorRef, new RefreshSetupMasterActorData(
149                     netconfTopologyDeviceSetup, remoteDeviceId), actorResponseWaitTime);
150
151             future.onComplete(new OnComplete<Object>() {
152                 @Override
153                 public void onComplete(final Throwable failure, final Object success) {
154                     if (failure != null) {
155                         LOG.error("Failed to refresh master actor data", failure);
156                         return;
157                     }
158                     remoteDeviceConnector.startRemoteDeviceConnection(newMasterSalFacade());
159                 }
160             }, netconfTopologyDeviceSetup.getActorSystem().dispatcher());
161         }
162     }
163
164     private void stopDeviceConnectorAndActor() {
165         if (!stopped.compareAndSet(false, true)) {
166             return;
167         }
168         if (remoteDeviceConnector != null) {
169             remoteDeviceConnector.stopRemoteDeviceConnection();
170         }
171
172         if (masterActorRef != null) {
173             netconfTopologyDeviceSetup.getActorSystem().stop(masterActorRef);
174             masterActorRef = null;
175         }
176     }
177
178     protected MasterSalFacade newMasterSalFacade() {
179         return new MasterSalFacade(remoteDeviceId, netconfTopologyDeviceSetup.getActorSystem(), masterActorRef,
180                 actorResponseWaitTime, mountService, netconfTopologyDeviceSetup.getDataBroker());
181     }
182 }