0761299b03c934c40c870181231b1c7f544c8c8f
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk feature sdnr wt
4  *  ================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.ccsdk.features.sdnr.wt.devicemanager.housekeeping;
22
23 import com.google.common.util.concurrent.FluentFuture;
24 import com.google.common.util.concurrent.Futures;
25 import com.google.common.util.concurrent.ListenableFuture;
26
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.NoSuchElementException;
30 import java.util.Optional;
31 import java.util.concurrent.ExecutionException;
32 import java.util.concurrent.Executors;
33 import java.util.concurrent.Future;
34 import java.util.concurrent.ScheduledExecutorService;
35 import java.util.concurrent.TimeUnit;
36 import java.util.concurrent.TimeoutException;
37 import org.eclipse.jdt.annotation.NonNull;
38 import org.eclipse.jdt.annotation.Nullable;
39 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.DataProvider;
40 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.NetworkElementConnectionEntitiyUtil;
41 import org.onap.ccsdk.features.sdnr.wt.devicemanager.types.InternalConnectionStatus;
42 import org.opendaylight.mdsal.binding.api.DataBroker;
43 import org.opendaylight.mdsal.binding.api.ReadTransaction;
44 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
45 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
46 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.ConnectionLogStatus;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.NetworkElementConnectionBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.NetworkElementConnectionEntity;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 public class ConnectionStatusHousekeepingService implements ClusterSingletonService, AutoCloseable {
64
65     private static final Logger LOG = LoggerFactory.getLogger(ConnectionStatusHousekeepingService.class);
66
67     private static final long INTERVAL_SECONDS = 30;
68     private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID =
69             InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
70                     new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())));
71     private static final ServiceGroupIdentifier IDENT =
72             ServiceGroupIdentifier.create("ConnectionStatusHousekeepingService");
73
74     private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);
75     private final DataBroker dataBroker;
76     private final DataProvider dataProvider;
77     private boolean isMaster;
78     private Future<?> taskReference;
79
80     private final Runnable runner = () -> doClean();
81
82     public ConnectionStatusHousekeepingService(DataBroker dataBroker, DataProvider dataProvider) {
83         this.dataBroker = dataBroker;
84         this.dataProvider = dataProvider;
85         this.start();
86     }
87
88     public void start() {
89         if (taskReference != null) {
90             taskReference.cancel(false);
91         }
92         if (!isMaster) {
93             LOG.info("do not start. not the master node");
94             return;
95         }
96         LOG.info("starting scheduler with interval {}", INTERVAL_SECONDS);
97         this.taskReference =
98                 this.scheduler.scheduleAtFixedRate(runner, INTERVAL_SECONDS, INTERVAL_SECONDS, TimeUnit.SECONDS);
99     }
100
101     private void doClean() {
102         LOG.debug("start housekeeping");
103         // get all devices from networkelement-connection index
104         try {
105             List<NetworkElementConnectionEntity> list = this.dataProvider.getNetworkElementConnections();
106
107             ConnectionLogStatus dbStatus;
108             ConnectionLogStatus mdsalStatus;
109             String nodeId;
110             if (list == null || list.size() <= 0) {
111                 LOG.trace("no items in list.");
112             } else {
113                 //check all db entries and sync connection status
114                 for (NetworkElementConnectionEntity item : list) {
115
116                     // compare with MD-SAL
117                     nodeId = item.getNodeId();
118                     LOG.trace("check status of {}", nodeId);
119                     dbStatus = item.getStatus();
120                     mdsalStatus = this.getMDSalConnectionStatus(nodeId);
121                     if (mdsalStatus == null) {
122                         LOG.trace("unable to get connection status. jump over");
123                         continue;
124                     }
125                     // if different then update db
126                     if (dbStatus != mdsalStatus) {
127                         LOG.trace("status is inconsistent db={}, mdsal={}. updating db", dbStatus, mdsalStatus);
128                         if ((item.isIsRequired() == null || item.isIsRequired() == false)
129                                 && mdsalStatus == ConnectionLogStatus.Disconnected) {
130                             LOG.info("removing entry for node {} ({}) from database due missing MD-SAL entry",
131                                     item.getNodeId(), mdsalStatus);
132                             this.dataProvider.removeNetworkConnection(nodeId);
133                         } else {
134                             this.dataProvider.updateNetworkConnectionDeviceType(
135                                     new NetworkElementConnectionBuilder().setStatus(mdsalStatus).build(), nodeId);
136                         }
137                     } else {
138                         LOG.trace("no difference");
139                     }
140
141                 }
142             }
143             //check all md-sal entries and add non-existing to db
144             //                  List<Node> mdsalNodes = this.getMDSalNodes();
145             //                  NodeId nid;
146             //                  for (Node mdsalNode : mdsalNodes) {
147             //                          nid = mdsalNode.getNodeId();
148             //                          if (nid == null) {
149             //                                  continue;
150             //                          }
151             //                          nodeId = nid.getValue();
152             //                          if (nodeId == null) {
153             //                                  continue;
154             //                          }
155             //                          if (contains(list, nodeId)) {
156             //                                  LOG.debug("found mountpoint for {} without db entry. creating.",nodeId);
157             //                                  this.dataProvider.updateNetworkConnection22(NetworkElementConnectionEntitiyUtil
158             //                                                  .getNetworkConnection(nodeId, mdsalNode.augmentation(NetconfNode.class)), nodeId);
159             //                          }
160             //                  }
161
162         } catch (Exception e) {
163             LOG.warn("problem executing housekeeping task: {}", e);
164         }
165         LOG.debug("finish housekeeping");
166     }
167
168     /**
169      * @param list
170      * @param nodeId
171      * @return
172      */
173     //  private boolean contains(List<NetworkElementConnectionEntity> list, @NonNull String nodeId) {
174     //          if(list==null || list.size()<=0) {
175     //                  return false;
176     //          }
177     //          for(NetworkElementConnectionEntity item:list) {
178     //                  if(item!=null && nodeId.equals(item.getNodeId())) {
179     //                          return true;
180     //                  }
181     //          }
182     //          return false;
183     //  }
184     //
185     //  private List<Node> getMDSalNodes(){
186     //          ReadTransaction trans = this.dataBroker.newReadOnlyTransaction();
187     //        FluentFuture<Optional<Topology>> optionalTopology =trans.read(LogicalDatastoreType.OPERATIONAL, NETCONF_TOPO_IID);
188     //        List<Node> nodes = new ArrayList<>();
189     //        try {
190     //          Topology topo = optionalTopology.get(20, TimeUnit.SECONDS).get();
191     //          List<Node> topoNodes=topo.getNode();
192     //          if(topoNodes!=null){
193     //                  nodes.addAll(topoNodes);
194     //          }
195     //        }
196     //        catch(Exception e) {
197     //          LOG.warn("unable to read netconf topology for housekeeping: {}",e);
198     //        }
199     //        return nodes;
200     //    }
201     private ConnectionLogStatus getMDSalConnectionStatus(String nodeId) {
202
203         @SuppressWarnings("null")
204         @NonNull
205         InstanceIdentifier<Node> instanceIdentifier =
206                 NETCONF_TOPO_IID.child(Node.class, new NodeKey(new NodeId(nodeId)));
207         ReadTransaction trans = this.dataBroker.newReadOnlyTransaction();
208         FluentFuture<Optional<Node>> optionalNode = trans.read(LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
209         try {
210             Node node = optionalNode.get(5, TimeUnit.SECONDS).get();
211             LOG.debug("node is {}", node);
212             NetconfNode nNode = node.augmentation(NetconfNode.class);
213             LOG.debug("nnode is {}", nNode);
214             if (nNode != null) {
215                 return InternalConnectionStatus.statusFromNodeStatus(nNode.getConnectionStatus());
216             }
217         } catch (NoSuchElementException e) {
218             return ConnectionLogStatus.Disconnected;
219         } catch (ExecutionException | InterruptedException | TimeoutException e) {
220             LOG.warn("unable to get node info: {}", e);
221         } finally {
222             trans.close();
223         }
224
225         return null;
226     }
227
228     @Override
229     public void close() throws Exception {
230         if (taskReference != null) {
231             taskReference.cancel(false);
232         }
233         this.scheduler.shutdown();
234     }
235
236     @SuppressWarnings("null")
237     @Override
238     public @NonNull ServiceGroupIdentifier getIdentifier() {
239         return IDENT;
240     }
241
242     @Override
243     public void instantiateServiceInstance() {
244         LOG.info("We take Leadership");
245         this.isMaster = true;
246         this.start();
247     }
248
249     @Override
250     public ListenableFuture<? extends Object> closeServiceInstance() {
251         LOG.info("We lost Leadership");
252         this.isMaster = false;
253         this.start();
254         return Futures.immediateFuture(null);
255     }
256 }