a79e4ad05be294a71376de13af7d73b305db0c16
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 /**
19         ecompProvider.sendProblemNotification(ownKeyName, notificationXml);
20  * ECOMP Messages are generated an send to destination
21  *
22  * @author herbert
23  */
24 package org.onap.ccsdk.features.sdnr.wt.devicemanager.dcaeconnector.impl;
25
26 import java.io.IOException;
27 import java.net.HttpURLConnection;
28 import java.net.MalformedURLException;
29 import java.net.URL;
30 import java.net.URLConnection;
31 import java.util.Optional;
32 import javax.net.ssl.HostnameVerifier;
33 import javax.net.ssl.HttpsURLConnection;
34 import javax.net.ssl.SSLContext;
35 import org.eclipse.jdt.annotation.Nullable;
36 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.NetconfTimeStamp;
37 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.types.NetconfTimeStampImpl;
38 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.DeviceManagerImpl;
39 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.InternalSeverity;
40 import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.ProblemNotificationXml;
41 import org.onap.ccsdk.features.sdnr.wt.devicemanager.ne.service.InventoryProvider;
42 import org.onap.ccsdk.features.sdnr.wt.devicemanager.ne.service.NetworkElement;
43 import org.onap.ccsdk.features.sdnr.wt.devicemanager.types.InventoryInformationDcae;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class DcaeMessages {
48
49     private static final Logger LOG = LoggerFactory.getLogger(DcaeSenderImpl.class);
50
51     private static final String DCAE_NORMAL = "NORMAL";
52     private static final String DCAE_MINOR = "MINOR";
53     private static final String DCAE_WARNING = "WARNING";
54     private static final String DCAE_CRITICAL = "CRITICAL";
55     private static final String DCAE_MAJOR = "MAJOR";
56
57     private static final String eventNamePrefix = "fault_Microwave_Radio_Alarms";
58     private static final String eventType = "Microwave_Radio_Alarms";
59     private static final String eventSourceType = "Microwave_Radio";
60
61     private static final String charset = "UTF-8";
62
63     private static final HostnameVerifier allHostsValid = (hostname, session) -> true;
64
65     private static final String CONTENT_TYPE_APPJSON = "application/json";
66
67     private static final NetconfTimeStamp NETCONFTIME_CONVERTER = NetconfTimeStampImpl.getConverter();
68
69     //Configurable parameters
70     private final DcaeSender dcaeSender;
71     private final int heartbeatIntervallSeconds;
72     private final String entityName;
73     private final DeviceManagerImpl deviceManager;
74
75     //Variables
76     private int heartbeatsequence = 0;
77
78     public DcaeMessages(DcaeSender ecompSender, String entityName, Integer heartbeatIntervallSeconds,
79             DeviceManagerImpl deviceManager) {
80         this.dcaeSender = ecompSender;
81         this.entityName = entityName;
82         this.deviceManager = deviceManager;
83         this.heartbeatIntervallSeconds = heartbeatIntervallSeconds;
84     }
85
86     /**
87      * Create a heartbeat message.
88      *
89      * @return Result string with answer from server
90      */
91     public String postHeartBeat() {
92         String epochTimeMicrosecondsString = getEpochTimeMicroseconds();
93         String body = assembleHeartbeatFromTemplate(null, epochTimeMicrosecondsString, heartbeatsequence++,
94                 NETCONFTIME_CONVERTER.getTimeStampAsNetconfString()).toString();
95         return dcaeSender.sendDcaePost(body);
96     }
97
98     /**
99      * ONF 1.2 Problem Notification
100      *
101      * @param mountPointName self-explaining
102      * @param notification Notification input
103      * @return String with answer
104      */
105
106     public String postNotification(String mountPointName, ProblemNotificationXml notification) {
107
108         String problemName = notification.getProblem();
109         String sequence = notification.getCounter();
110         String objId = notification.getObjectId();
111         String severity = convert(notification.getSeverity());
112         String timeStamp = convert(notification.getTimeStamp());
113
114         String body = assembleEventNotificationFromTemplate(null, timeStamp, sequence, mountPointName, objId,
115                 problemName, severity, notification.getTimeStamp()).toString();
116
117         return dcaeSender.sendDcaePost(body);
118     }
119
120     /**
121      * Setup a connection to URL with authorisation header
122      *
123      * @param url e.g. "https://plan.fritz.box:9092/ux/#" or "
124      * @param basicAuth authorisation header like "Basic SGVyYmVydDpIZXJiZXJ0"
125      * @param insertContentHeader
126      * @return Null in case of error or the URLConnection
127      * @throws IOException
128      * @throws MalformedURLException
129      */
130     static @Nullable HttpURLConnection openConnection(URL url, String basicAuth, boolean insertContentHeader,
131             @Nullable SSLContext sc) throws MalformedURLException, IOException {
132
133         //Prepare the connection
134         HttpURLConnection newHttpConnection = null;
135         {
136             URLConnection newConnection = url.openConnection();
137             if (newConnection instanceof HttpURLConnection) {
138                 LOG.debug("Setup connection to {} ", url.toString());
139
140                 newHttpConnection = (HttpURLConnection) newConnection;
141
142                 newHttpConnection.setDoOutput(true); // Triggers POST.
143                 newHttpConnection.setRequestProperty("Accept-Charset", charset);
144                 if (basicAuth != null) {
145                     newHttpConnection.setRequestProperty("Authorization", basicAuth);
146                 }
147                 if (insertContentHeader) {
148                     newHttpConnection.setRequestProperty("Content-Type", CONTENT_TYPE_APPJSON);
149                 }
150
151                 if (newHttpConnection instanceof HttpsURLConnection) {
152                     LOG.debug("SSL connection setup with trust all.");
153                     HttpsURLConnection newHttpsConnection = (HttpsURLConnection) newHttpConnection;
154                     if (sc != null) {
155                         newHttpsConnection.setSSLSocketFactory(sc.getSocketFactory());
156                     } else {
157                         LOG.warn("No SSL Contect available");
158                     }
159                     newHttpsConnection.setHostnameVerifier(allHostsValid);
160                 }
161             } else {
162                 LOG.warn("URL not a HTTP protocol: {}", url);
163             }
164         }
165         return newHttpConnection;
166     }
167
168     /* -----------------
169      * Private function for message creation and with templates
170      */
171
172     /**
173      * Get actual microseconds
174      *
175      * @return String
176      */
177     private String getEpochTimeMicroseconds() {
178         long microseconds = System.nanoTime() / 1000;
179         return String.valueOf(microseconds);
180     }
181
182     /**
183      * Assemble heartbeat message
184      *
185      * @param sb StringBuffer to be used or null to allocate
186      * @param epochTimeMicrosecondsString Text with time stamp
187      * @param sequence integer sequence number
188      * @param eventTimeValueNetconfFormatString like this: 2018-05-14T05:32:17.292Z
189      * @return StringBuffer with result
190      */
191     private StringBuffer assembleHeartbeatFromTemplate(StringBuffer sb, String epochTimeMicrosecondsString,
192             int sequence, String eventTimeValueNetconfFormatString) {
193
194         if (sb == null) {
195             sb = new StringBuffer();
196         }
197         // @formatter:off
198         sb.append("{\n"
199                 + "    \"event\": {\n"
200                 + "        \"commonEventHeader\": {\n"
201                 + "            \"domain\": \"heartbeat\",\n"
202                 + "            \"eventId\": \"testpattern-ab305d54-85b4-a31b-7db2-fb6b9e546015\",\n"
203                 + "            \"eventName\": \"heartbeat_Controller\",\n"
204                 + "            \"eventType\": \"Controller\",\n"
205                 + "            \"priority\": \"Low\",\n"
206                 + "            \"reportingEntityId\": \"\",\n"
207                 + "            \"reportingEntityName\": \"" + entityName + "\",\n"
208                 + "            \"sequence\": " + String.valueOf(sequence) + ",\n"
209                 + "            \"sourceId\": \"\",\n"
210                 + "            \"sourceName\": \"" + entityName + "\",\n"
211                 + "            \"startEpochMicrosec\": " + epochTimeMicrosecondsString + ",\n"
212                 + "            \"lastEpochMicrosec\": " + epochTimeMicrosecondsString + ",\n"
213                 + "            \"version\": 3.0\n"
214                 + "        },\n"
215                 + "        \"heartbeatFields\": {\n"
216                 + "            \"additionalFields\": [\n"
217                 + "                 {\n"
218                 + "                   \"name\": \"eventTime\",\n"
219                 + "                   \"value\": \"" + eventTimeValueNetconfFormatString + "\"\n"
220                 + "                 }\n"
221                 + "            ],\n"
222                 + "            \"heartbeatFieldsVersion\": 1.0,\n"
223                 + "            \"heartbeatInterval\": " + heartbeatIntervallSeconds + "\n"
224                 + "        }\n"
225                 + "    }\n"
226                 + "}\n");
227         // @formatter:on
228
229         return sb;
230     }
231
232     /**
233      * Assemble notification message
234      *
235      * @param sb StringBuffer to be used or null to allocate
236      * @param epochTimeMicrosecondsString Text with time stamp
237      * @param sequence integer sequence number
238      * @param mountpointName
239      * @param objId
240      * @param problemName
241      * @param severity
242      * @return StringBuffer with result
243      */
244
245     private StringBuffer assembleEventNotificationFromTemplate(StringBuffer sb, String epochTimeMicrosecondsString,
246             String sequence, String mountpointName, String objId, String problemName, String severity,
247             String eventTimeValueNetconfFormatString) {
248
249         if (sb == null) {
250             sb = new StringBuffer();
251         }
252
253         NetworkElement optionalNe =
254                 deviceManager != null ? deviceManager.getNeByMountpoint(mountpointName) : null;
255         InventoryInformationDcae neInventory = InventoryInformationDcae.getDefault();
256         if (optionalNe != null) {
257             Optional<InventoryProvider> inventoryProvider = optionalNe.getService(InventoryProvider.class);
258             if (inventoryProvider.isPresent()) {
259                 neInventory = inventoryProvider.get().getInventoryInformation();
260             }
261         }
262
263         // @formatter:off
264         sb.append("{\n"
265                 + "    \"event\": {\n"
266                 + "        \"commonEventHeader\": {\n"
267                 + "            \"domain\": \"fault\",\n"
268                 + "            \"eventId\": \"" + mountpointName + "_" + objId + "_" + problemName + "\",\n"
269                 + "            \"eventName\": \"" + eventNamePrefix + "_" + problemName + "\",\n"
270                 + "            \"eventType\": \"" + eventType + "\",\n"
271                 + "            \"sequence\": " + sequence + ",\n"
272                 + "            \"priority\": \"High\",\n"
273                 + "            \"reportingEntityId\": \"\",\n"
274                 + "            \"reportingEntityName\": \"" + entityName + "\",\n"
275                 + "            \"sourceId\": \"\",\n"
276                 + "            \"sourceName\": \"" + mountpointName + "\",\n"
277                 + "            \"startEpochMicrosec\": " + epochTimeMicrosecondsString + ",\n"
278                 + "            \"lastEpochMicrosec\": " + epochTimeMicrosecondsString + ",\n"
279                 + "            \"version\": 3.0\n"
280                 + "        },\n"
281                 + "        \"faultFields\": {\n"
282                 + "            \"alarmAdditionalInformation\": [\n"
283                 + "                 {\n"
284                 + "                   \"name\": \"eventTime\",\n"
285                 + "                   \"value\": \"" + eventTimeValueNetconfFormatString + "\"\n"
286                 + "                 },\n"
287                 + "                 {\n"
288                 + "                   \"name\": \"equipType\",\n"
289                 + "                   \"value\": \"" + neInventory.getType() + "\"\n"
290                 + "                 },\n"
291                 + "                 {\n"
292                 + "                   \"name\": \"vendor\",\n"
293                 + "                   \"value\": \"" + neInventory.getVendor() + "\"\n"
294                 + "                 },\n" + "                 {\n"
295                 + "                   \"name\": \"model\",\n"
296                 + "                   \"value\": \"" + neInventory.getModel() + "\"\n"
297                 + "                 }\n"
298                 + "            ],\n"
299                 + "            \"faultFieldsVersion\":2.0,\n"
300                 + "            \"eventSourceType\": \"" + eventSourceType  + "\",\n"
301                 + "            \"alarmCondition\": \"" + problemName + "\",\n"
302                 + "            \"alarmInterfaceA\": \"" + objId + "\",\n"
303                 + "            \"specificProblem\": \"" + problemName + "\",\n"
304                 + "            \"eventSeverity\": \"" + severity + "\",\n"
305                 + "            \"vfStatus\": \"Active\"\n"
306                 + "        }\n"
307                 + "    }\n"
308                 + "}\n");
309         // @formatter:on
310
311         return sb;
312     }
313
314     /* -----------------
315      * Convert internal type formats into the Ecomp format
316      */
317
318     private String convert(InternalSeverity severity) {
319         switch (severity) {
320             case NonAlarmed:
321                 break;
322             case Warning:
323                 return DCAE_WARNING;
324             case Minor:
325                 return DCAE_MINOR;
326             case Major:
327                 return DCAE_MAJOR;
328             case Critical:
329                 return DCAE_CRITICAL;
330         }
331         return DCAE_NORMAL;
332     }
333
334
335     /**
336      * Time has to be converted into milliseconds
337      *
338      * @param timeAsString time as string
339      * @return as string
340      */
341     private String convert(String timeAsString) {
342
343         long microseconds = -1;
344         try {
345             microseconds = NETCONFTIME_CONVERTER.getTimeStampFromNetconfAsMilliseconds(timeAsString) * 1000;
346         } catch (IllegalArgumentException e) {
347             LOG.info("Can not convert timeAsString", e);
348         }
349         return String.valueOf(microseconds);
350     }
351
352
353 }