2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021-2022 Wipro Limited.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.ccsdk.features.sdnr.northbound.addCMHandle;
23 import com.fasterxml.jackson.core.JsonProcessingException;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.google.common.util.concurrent.ListenableFuture;
27 import java.io.FileInputStream;
28 import java.io.IOException;
29 import java.sql.Timestamp;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.List;
35 import java.util.Objects;
36 import java.util.Properties;
38 import org.eclipse.jdt.annotation.NonNull;
39 import org.onap.ccsdk.features.sdnr.northbound.addCMHandle.HttpRequester;
40 import org.onap.ccsdk.features.sdnr.northbound.addCMHandle.models.CpsCmHandleRequestBody;
41 import org.onap.ccsdk.sli.core.utils.common.EnvProperties;
42 import org.opendaylight.mdsal.binding.api.DataBroker;
43 import org.opendaylight.mdsal.binding.api.DataObjectModification;
44 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
45 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
46 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
47 import org.opendaylight.mdsal.binding.api.DataTreeModification;
48 import org.opendaylight.mdsal.binding.api.MountPointService;
49 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
50 import org.opendaylight.mdsal.binding.api.RpcProviderService;
51 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
52 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
53 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
54 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
55 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.AddCMHandleInput;
56 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.AddCMHandleOutput;
57 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.AddCMHandleOutputBuilder;
58 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.CMHandleAPIService;
59 import org.opendaylight.yang.gen.v1.org.onap.ccsdk.rev210615.status.StatusBuilder;
60 import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.DmiRegistryBuilder;
61 import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.dmi.registry.CmHandle;
62 import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.dmi.registry.CmHandleBuilder;
63 import org.opendaylight.yang.gen.v1.org.onap.cps.ncmp.rev210520.dmi.registry.CmHandleKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
71 import org.opendaylight.yangtools.concepts.ListenerRegistration;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.opendaylight.yangtools.yang.common.RpcResult;
74 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
75 import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
79 public class AddCMHandleProvider implements CMHandleAPIService, AutoCloseable {
81 private static final Logger LOG = LoggerFactory.getLogger(AddCMHandleProvider.class);
82 private final ObjectMapper objMapper = new ObjectMapper();
83 private final String APPLICATION_NAME = "addCMHandle";
84 private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR";
85 private static final String PROPERTIES_FILE_NAME = "cm-handle.properties";
86 private static HashMap<String, String> config;
87 private ListenerRegistration<AddCmHandleListener> listener;
88 private static final @NonNull InstanceIdentifier<Node> NETCONF_NODE_TOPO_IID =
89 InstanceIdentifier.create(NetworkTopology.class)
90 .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())))
92 private static final @NonNull DataTreeIdentifier<Node> NETCONF_NODE_TOPO_TREE_ID =
93 DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, NETCONF_NODE_TOPO_IID);
95 private DataBroker dataBroker;
96 private MountPointService mountPointService;
97 private DOMMountPointService domMountPointService;
98 private RpcProviderService rpcProviderRegistry;
99 @SuppressWarnings("unused")
100 private NotificationPublishService notificationPublishService;
101 @SuppressWarnings("unused")
102 private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
103 private YangParserFactory yangParserFactory;
104 private BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer;
105 private Boolean isInitializationSuccessful = false;
106 private Long lastNotificationSentOn = Long.valueOf(0);
107 private List<String> nodeIdList = new ArrayList<>();
109 public AddCMHandleProvider() {
111 LOG.info("Creating provider for {}", APPLICATION_NAME);
112 this.dataBroker = null;
113 this.mountPointService = null;
114 this.domMountPointService = null;
115 this.rpcProviderRegistry = null;
116 this.notificationPublishService = null;
117 this.clusterSingletonServiceProvider = null;
118 this.yangParserFactory = null;
119 this.bindingNormalizedNodeSerializer = null;
123 public void setDataBroker(DataBroker dataBroker) {
124 this.dataBroker = dataBroker;
127 public void setRpcProviderRegistry(RpcProviderService rpcProviderRegistry) {
128 this.rpcProviderRegistry = rpcProviderRegistry;
131 public void setNotificationPublishService(NotificationPublishService notificationPublishService) {
132 this.notificationPublishService = notificationPublishService;
135 public void setMountPointService(MountPointService mountPointService) {
136 this.mountPointService = mountPointService;
139 public void setDomMountPointService(DOMMountPointService domMountPointService) {
140 this.domMountPointService = domMountPointService;
143 public void setClusterSingletonService(ClusterSingletonServiceProvider clusterSingletonService) {
144 this.clusterSingletonServiceProvider = clusterSingletonService;
147 public void setYangParserFactory(YangParserFactory yangParserFactory) {
148 this.yangParserFactory = yangParserFactory;
151 public void setBindingNormalizedNodeSerializer(BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer) {
152 this.bindingNormalizedNodeSerializer = bindingNormalizedNodeSerializer;
153 LOG.info("Init bindingNormalizedNodeSerializer");
156 public Boolean isInitializationSuccessful() {
157 return isInitializationSuccessful;
161 LOG.info("Initializing {} for {}", this.getClass().getName(), APPLICATION_NAME);
163 String propDir = System.getenv(SDNC_CONFIG_DIR);
164 if (propDir == null) {
165 LOG.error("Environment variable SDNC_CONFIG_DIR is not set");
166 propDir = "/opt/onap/ccsdk/data/properties/";
167 } else if (!propDir.endsWith("/")) {
168 propDir = propDir + "/";
171 config = new HashMap<String, String>();
173 try (FileInputStream fileInput = new FileInputStream(propDir + PROPERTIES_FILE_NAME)) {
174 EnvProperties properties = new EnvProperties();
175 properties.load(fileInput);
177 for (String param : new String[] {"cpsUrl", "user", "password", "dmaapUrl", "dmiServiceName", "client",
179 config.put(param, properties.getProperty(param));
181 } catch (IOException e) {
182 LOG.error("Error while reading properties file: ", e);
185 listener = dataBroker.registerDataTreeChangeListener(NETCONF_NODE_TOPO_TREE_ID, new AddCmHandleListener());
186 isInitializationSuccessful = true;
187 LOG.info("Initialization complete for {}", APPLICATION_NAME);
188 LOG.info("addCMHandle Session Initiated");
192 * AddCmHandleListener
194 private class AddCmHandleListener implements DataTreeChangeListener<Node> {
197 public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) {
198 LOG.info("AddCmHandleListener TreeChange enter changes: {}", changes.size());
199 LOG.info("config: " + config);
200 String nodeId = getNodeId(changes);
201 if (Objects.nonNull(nodeId) && !(nodeIdList.contains(nodeId))) {
202 nodeIdList.add(nodeId);
204 Timestamp currentTime = new Timestamp(System.currentTimeMillis());
205 Long difference = currentTime.getTime() - lastNotificationSentOn;
206 if (difference > Long.valueOf(config.get("timerThreshold"))) {
207 sendNotification(nodeIdList);
215 * Method to get nodeId.
217 private String getNodeId(@NonNull Collection<DataTreeModification<Node>> changes) {
218 String nodeIdString = null;
219 for (final DataTreeModification<Node> change : changes) {
221 final DataObjectModification<Node> root = change.getRootNode();
223 ModificationType modificationTyp = root.getModificationType();
224 if ((modificationTyp != ModificationType.DELETE)) {
226 Node node = root.getDataAfter();
227 NodeId nodeId = node != null ? node.getNodeId() : null;
228 if (nodeId == null) {
229 LOG.info("without nodeid");
231 nodeIdString = nodeId.getValue();
232 LOG.info("AddCmHandle for nodeId: {}", nodeIdString);
236 } catch (NullPointerException | IllegalStateException e) {
237 LOG.info("Data not available at ", e);
245 * Method called when cm-handle notification is to be sent.
247 protected void sendNotification(List<String> nodeIdList) {
249 String sendNotificationTo = config.get("client");
250 lastNotificationSentOn = new Timestamp(System.currentTimeMillis()).getTime();
251 if (sendNotificationTo.equalsIgnoreCase("CPS")) {
252 sendNotificationToCps(nodeIdList);
255 if (sendNotificationTo.equalsIgnoreCase("DMAAP")) {
256 sendNotificationToDmaap(nodeIdList);
260 sendNotificationToCps(nodeIdList);
261 sendNotificationToDmaap(nodeIdList);
263 lastNotificationSentOn = new Timestamp(System.currentTimeMillis()).getTime();
268 * Method called when cm-handle notification is to be sent to CPS.
270 protected String sendNotificationToCps(List<String> nodeIdList) {
272 LOG.info("Sending Notification to CPS");
273 String userCredential = config.get("user") + ":" + config.get("password");
274 String url = config.get("cpsUrl");
275 String requestBody = null;
276 CpsCmHandleRequestBody cpsCmHandleRequestBody = new CpsCmHandleRequestBody(nodeIdList);
277 LOG.info("url {}", url);
278 LOG.info("userCredential: {}", userCredential);
280 requestBody = objMapper.writeValueAsString(cpsCmHandleRequestBody);
281 LOG.info("requestBody{} ", requestBody);
282 } catch (JsonProcessingException e) {
283 LOG.error("ERROR: {}", e);
285 String response = HttpRequester.sendPostRequest(url, userCredential, requestBody);
286 LOG.info("response from CPS: {} ", response);
292 * Method called when cm-handle notification is to be sent to Dmaap.
294 protected String sendNotificationToDmaap(List<String> nodeIdList) {
296 LOG.info("Sending Notification to Dmaap");
297 String url = config.get("dmaapUrl");
298 Map<CmHandleKey, CmHandle> values = new HashMap<>();
299 nodeIdList.forEach(nodeId -> {
300 CmHandleBuilder cmHandleBuilder = new CmHandleBuilder();
301 cmHandleBuilder.setDmiServiceName(config.get("dmiServiceName"));
302 cmHandleBuilder.setId(nodeId);
303 CmHandleKey cmHandleKey = new CmHandleKey(nodeId);
304 values.put(cmHandleKey, cmHandleBuilder.build());
306 DmiRegistryBuilder dmiRegistryBuilder = new DmiRegistryBuilder();
307 dmiRegistryBuilder.setCmHandle(values);
309 String requestBody = null;
310 LOG.info("url: {}", url);
312 requestBody = objMapper.writeValueAsString(dmiRegistryBuilder.build());
313 LOG.info("requestBody: {}", requestBody);
314 } catch (JsonProcessingException e) {
315 LOG.error("ERROR: {}", e);
317 String response = HttpRequester.sendPostRequest(url, null, requestBody);
318 LOG.info("response from Dmaap: {}", response);
324 * Method called when the blueprint container is destroyed.
327 public void close() {
328 if (Objects.nonNull(listener)) {
331 LOG.debug("AddCMHandleProvider Closed");
335 public ListenableFuture<RpcResult<AddCMHandleOutput>> addCMHandle(AddCMHandleInput input) {
336 StatusBuilder statusBuilder = new StatusBuilder();
337 statusBuilder.setMessage("SUCCESS");
338 return RpcResultBuilder.success(new AddCMHandleOutputBuilder().setStatus(statusBuilder.build()).build())