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