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