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