1 /*******************************************************************************
2 * ============LICENSE_START=======================================================
3 * ONAP : ccsdk feature sdnr wt
4 * ================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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;
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;
58 public class ConnectionStatusHousekeepingService implements ClusterSingletonService,AutoCloseable {
60 private static final Logger LOG = LoggerFactory.getLogger(ConnectionStatusHousekeepingService.class);
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");
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;
74 private final Runnable runner = () -> doClean();
76 public ConnectionStatusHousekeepingService(DataBroker dataBroker, DataProvider dataProvider) {
77 this.dataBroker = dataBroker;
78 this.dataProvider = dataProvider;
83 if (taskReference != null) {
84 taskReference.cancel(false);
87 LOG.info("do not start. not the master node");
90 LOG.info("starting scheduler with interval {}", INTERVAL_SECONDS);
91 this.taskReference = this.scheduler.scheduleAtFixedRate(runner, INTERVAL_SECONDS, INTERVAL_SECONDS,
95 private void doClean() {
96 LOG.debug("start housekeeping");
97 // get all devices from networkelement-connection index
99 List<NetworkElementConnectionEntity> list = this.dataProvider.getNetworkElementConnections();
101 ConnectionLogStatus dbStatus;
102 ConnectionLogStatus mdsalStatus;
104 if (list == null || list.size() <= 0) {
105 LOG.trace("no items in list.");
108 for (NetworkElementConnectionEntity item : list) {
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");
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);
126 this.dataProvider.updateNetworkConnectionDeviceType(
127 new NetworkElementConnectionBuilder().setStatus(mdsalStatus).build(), nodeId);
130 LOG.trace("no difference");
134 } catch (Exception e) {
135 LOG.warn("problem executing housekeeping task: {}", e);
137 LOG.debug("finish housekeeping");
140 private ConnectionLogStatus getMDSalConnectionStatus(String nodeId) {
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);
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);
153 return InternalConnectionStatus.statusFromNodeStatus(nNode.getConnectionStatus());
155 } catch (NoSuchElementException e) {
156 return ConnectionLogStatus.Disconnected;
157 } catch (ExecutionException | InterruptedException | TimeoutException e) {
158 LOG.warn("unable to get node info: {}", e);
165 public void close() throws Exception {
166 if (taskReference != null) {
167 taskReference.cancel(false);
169 this.scheduler.shutdown();
172 @SuppressWarnings("null")
174 public @NonNull ServiceGroupIdentifier getIdentifier() {
179 public void instantiateServiceInstance() {
180 LOG.info("We take Leadership");
186 public ListenableFuture<? extends Object> closeServiceInstance() {
187 LOG.info("We lost Leadership");
190 return Futures.immediateFuture(null);