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