1628fba1b1a9a1a7794a4d04f4f6c8a47dfb7fa5
[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 import java.util.List;
27 import java.util.NoSuchElementException;
28 import java.util.Optional;
29 import java.util.concurrent.ExecutionException;
30 import java.util.concurrent.Executors;
31 import java.util.concurrent.Future;
32 import java.util.concurrent.ScheduledExecutorService;
33 import java.util.concurrent.TimeUnit;
34 import java.util.concurrent.TimeoutException;
35 import org.eclipse.jdt.annotation.NonNull;
36 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.DataProvider;
37 import org.onap.ccsdk.features.sdnr.wt.devicemanager.types.InternalConnectionStatus;
38 import org.opendaylight.mdsal.binding.api.DataBroker;
39 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
40 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
41 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.ConnectionLogStatus;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.NetworkElementConnectionBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.NetworkElementConnectionEntity;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
54 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 public class ConnectionStatusHousekeepingService implements ClusterSingletonService,AutoCloseable {
59
60     private static final Logger LOG = LoggerFactory.getLogger(ConnectionStatusHousekeepingService.class);
61
62     private static final long INTERVAL_SECONDS = 30;
63     private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID = InstanceIdentifier
64             .create(NetworkTopology.class)
65             .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())));
66     private static final ServiceGroupIdentifier IDENT = ServiceGroupIdentifier.create("ConnectionStatusHousekeepingService");
67
68     private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);
69     private final DataBroker dataBroker;
70     private final DataProvider dataProvider;
71     private boolean isMaster;
72     private Future<?> taskReference;
73
74     private final Runnable runner = () -> doClean();
75
76     public ConnectionStatusHousekeepingService(DataBroker dataBroker, DataProvider dataProvider) {
77         this.dataBroker = dataBroker;
78         this.dataProvider = dataProvider;
79         this.start();
80     }
81
82     public void start() {
83         if (taskReference != null) {
84             taskReference.cancel(false);
85         }
86         if(!isMaster) {
87             LOG.info("do not start. not the master node");
88             return;
89         }
90         LOG.info("starting scheduler with interval {}", INTERVAL_SECONDS);
91         this.taskReference = this.scheduler.scheduleAtFixedRate(runner, INTERVAL_SECONDS, INTERVAL_SECONDS,
92                 TimeUnit.SECONDS);
93     }
94
95     private void doClean() {
96         LOG.debug("start housekeeping");
97         // get all devices from networkelement-connection index
98         try {
99             List<NetworkElementConnectionEntity> list = this.dataProvider.getNetworkElementConnections();
100
101             ConnectionLogStatus dbStatus;
102             ConnectionLogStatus mdsalStatus;
103             String nodeId;
104             if (list == null || list.size() <= 0) {
105                 LOG.trace("no items in list.");
106                 return;
107             }
108             for (NetworkElementConnectionEntity item : list) {
109
110                 // compare with MD-SAL
111                 nodeId = item.getNodeId();
112                 LOG.trace("check status of {}", nodeId);
113                 dbStatus = item.getStatus();
114                 mdsalStatus = this.getMDSalConnectionStatus(nodeId);
115                 if (mdsalStatus == null) {
116                     LOG.trace("unable to get connection status. jump over");
117                     continue;
118                 }
119                 // if different then update db
120                 if (dbStatus != mdsalStatus) {
121                     LOG.trace("status is inconsistent db={}, mdsal={}. updating db", dbStatus, mdsalStatus);
122                     if(!item.isIsRequired() && mdsalStatus==ConnectionLogStatus.Disconnected) {
123                         this.dataProvider.removeNetworkConnection(nodeId);
124                     }
125                     else {
126                     this.dataProvider.updateNetworkConnectionDeviceType(
127                             new NetworkElementConnectionBuilder().setStatus(mdsalStatus).build(), nodeId);
128                     }
129                 } else {
130                     LOG.trace("no difference");
131                 }
132
133             }
134         } catch (Exception e) {
135             LOG.warn("problem executing housekeeping task: {}", e);
136         }
137         LOG.debug("finish housekeeping");
138     }
139
140     private ConnectionLogStatus getMDSalConnectionStatus(String nodeId) {
141
142         @SuppressWarnings("null")
143         @NonNull InstanceIdentifier<Node> instanceIdentifier = NETCONF_TOPO_IID.child(Node.class,
144                 new NodeKey(new NodeId(nodeId)));
145         FluentFuture<Optional<Node>> optionalNode = this.dataBroker.newReadOnlyTransaction()
146                 .read(LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
147         try {
148             Node node = optionalNode.get(5, TimeUnit.SECONDS).get();
149             LOG.debug("node is {}", node);
150             NetconfNode nNode = node.augmentation(NetconfNode.class);
151             LOG.debug("nnode is {}", nNode);
152             if (nNode != null) {
153                 return InternalConnectionStatus.statusFromNodeStatus(nNode.getConnectionStatus());
154             }
155         } catch (NoSuchElementException e) {
156             return ConnectionLogStatus.Disconnected;
157         } catch (ExecutionException | InterruptedException | TimeoutException e) {
158             LOG.warn("unable to get node info: {}", e);
159         }
160
161         return null;
162     }
163
164     @Override
165     public void close() throws Exception {
166         if (taskReference != null) {
167             taskReference.cancel(false);
168         }
169         this.scheduler.shutdown();
170     }
171
172      @SuppressWarnings("null")
173         @Override
174         public @NonNull ServiceGroupIdentifier getIdentifier() {
175              return IDENT;
176         }
177
178         @Override
179         public void instantiateServiceInstance() {
180             LOG.info("We take Leadership");
181             this.isMaster=true;
182             this.start();
183         }
184
185         @Override
186         public ListenableFuture<? extends Object> closeServiceInstance() {
187             LOG.info("We lost Leadership");
188             this.isMaster=false;
189             this.start();
190             return Futures.immediateFuture(null);
191         }
192 }