3d419926f13bac5f2afda1cfecd0b8097cb75b73
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.mso.apihandlerinfra;
22
23 import java.io.StringReader;
24 import java.io.StringWriter;
25 import java.sql.Timestamp;
26 import java.text.SimpleDateFormat;
27 import java.util.Date;
28
29 import javax.ws.rs.core.Response;
30 import javax.xml.bind.JAXBContext;
31 import javax.xml.bind.JAXBException;
32 import javax.xml.bind.Marshaller;
33 import javax.xml.bind.Unmarshaller;
34 import javax.xml.transform.OutputKeys;
35 import javax.xml.transform.Transformer;
36 import javax.xml.transform.TransformerFactory;
37 import javax.xml.transform.dom.DOMSource;
38 import javax.xml.transform.sax.SAXSource;
39 import javax.xml.transform.stream.StreamResult;
40
41 import org.hibernate.Session;
42 import org.w3c.dom.Document;
43 import org.w3c.dom.Element;
44 import org.w3c.dom.Node;
45 import org.w3c.dom.NodeList;
46 import org.xml.sax.InputSource;
47
48 import org.openecomp.mso.apihandler.common.ErrorNumbers;
49 import org.openecomp.mso.apihandler.common.ValidationException;
50 import org.openecomp.mso.apihandlerinfra.networkbeans.ActionType;
51 import org.openecomp.mso.apihandlerinfra.networkbeans.NetworkInputs;
52 import org.openecomp.mso.apihandlerinfra.networkbeans.NetworkRequest;
53 import org.openecomp.mso.apihandlerinfra.networkbeans.ObjectFactory;
54 import org.openecomp.mso.apihandlerinfra.networkbeans.RequestInfo;
55 import org.openecomp.mso.apihandlerinfra.networkbeans.RequestStatusType;
56 import org.openecomp.mso.logger.MessageEnum;
57 import org.openecomp.mso.logger.MsoLogger;
58 import org.openecomp.mso.properties.MsoJavaProperties;
59 import org.openecomp.mso.db.AbstractSessionFactoryManager;
60 import org.openecomp.mso.requestsdb.InfraActiveRequests;
61 import org.openecomp.mso.requestsdb.RequestsDatabase;
62 import org.openecomp.mso.requestsdb.RequestsDbSessionFactoryManager;
63
64 public class NetworkMsoInfraRequest {
65
66     private String requestId;
67     private String requestXML;
68     private String requestUri;
69     private RequestInfo rinfo;
70     private NetworkInputs networkInputs;
71     private String networkParams;
72     private ActionType action;
73     private String errorMessage;
74     private String httpResponse;
75     private String responseBody;
76     private RequestStatusType status;
77     private long startTime;
78     private long progress = Constants.PROGRESS_REQUEST_RECEIVED;
79
80     private static MsoLogger msoLogger = MsoLogger.getMsoLogger (MsoLogger.Catalog.APIH);
81     private static final String NOT_PROVIDED = "not provided";
82
83     protected AbstractSessionFactoryManager requestsDbSessionFactoryManager = new RequestsDbSessionFactoryManager ();
84     
85     NetworkMsoInfraRequest (String requestId) {
86         this.requestId = requestId;
87         this.startTime = System.currentTimeMillis();
88         MsoLogger.setLogContext (requestId, null);
89
90     }
91
92     // Parse request XML
93     void parse (String reqXML, String version, MsoJavaProperties props) throws ValidationException {
94
95         msoLogger.debug ("Validating the request");
96
97         this.requestXML = reqXML;
98
99         NetworkRequest networkReq = null;
100         boolean isWrongRootElement = false;
101
102         try {
103             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
104             Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller ();
105
106             InputSource inputSource = new InputSource (new StringReader (reqXML));
107             SAXSource source = new SAXSource (inputSource);
108
109             if (reqXML.contains ("network-request") && !reqXML.contains ("vnf-request")) {
110                 networkReq = jaxbUnmarshaller.unmarshal (source, NetworkRequest.class).getValue ();
111             } else {
112                 isWrongRootElement = true;
113             }
114
115         } catch (Exception e) {
116                  msoLogger.error (MessageEnum.APIH_VNFREQUEST_VALIDATION_ERROR, "", "", MsoLogger.ErrorCode.DataError, "Exception when parsing reqXML", e);
117             throw new ValidationException ("format for network request");
118         }
119
120         if (isWrongRootElement) {
121                 msoLogger.error (MessageEnum.APIH_REQUEST_VALIDATION_ERROR_REASON, "root element is not correct", "", "", MsoLogger.ErrorCode.DataError, "root element <network-request> expected");
122             throw new ValidationException ("root element <network-request> expected");
123         }
124
125         if (networkReq == null) {
126             throw new ValidationException ("network-request");
127         }
128
129         this.rinfo = networkReq.getRequestInfo ();
130
131         if (this.rinfo == null) {
132             throw new ValidationException ("request-info");
133         }
134         
135         action = this.rinfo.getAction ();
136         if (action == null) {
137             throw new ValidationException ("action");
138         }
139         
140         if (!InfraUtils.isActionAllowed (props, "network", version, action.value ())) {
141                 throw new ValidationException ("action allowable for version " + version + " of network request");              
142         }
143
144         this.networkInputs = networkReq.getNetworkInputs ();
145         if (this.networkInputs == null) {
146             throw new ValidationException ("network-inputs");
147         }
148         
149         // Verify that the elements correspond to the version
150
151         switch (version) {
152             case Constants.SCHEMA_VERSION_V1:
153                 if (this.networkInputs.getBackoutOnFailure() != null || this.networkInputs.getAicCloudRegion() != null
154                     ||
155                     this.networkInputs.getServiceInstanceId() != null) {
156                     throw new ValidationException("format for v1 version of network request");
157                 }
158                 break;
159             case Constants.SCHEMA_VERSION_V2:
160                 if (this.networkInputs.getServiceType() != null || this.networkInputs.getAicNodeClli() != null ||
161                     this.networkInputs.getServiceInstanceId() != null) {
162                     throw new ValidationException("format for v2 version of network request");
163                 }
164                 break;
165             case Constants.SCHEMA_VERSION_V3:
166                 if (this.networkInputs.getServiceType() != null || this.networkInputs.getAicNodeClli() != null) {
167                     throw new ValidationException("format for v3 version of network request");
168                 }
169                 break;
170         }
171
172         switch (action) {            
173             case UPDATE:
174             case DELETE:
175                 if (this.networkInputs.getNetworkId () == null) {
176                     throw new ValidationException ("network-id");
177                 }
178                 break;
179             default:
180                 break;
181         }
182
183         if (ActionType.CREATE.equals (action) && this.networkInputs.getNetworkName () == null) {
184             throw new ValidationException ("network-name");
185         }
186
187         if (this.networkInputs.getNetworkType () == null) {
188             throw new ValidationException ("network-type");
189         }
190         
191         if (!version.equals(Constants.SCHEMA_VERSION_V1) && this.networkInputs.getServiceId () == null) {
192                 throw new ValidationException ("service-id ");
193         }
194         
195         if (this.networkInputs.getServiceType () != null && this.networkInputs.getServiceId () != null) {
196                 throw new ValidationException ("service-type or service-id ");
197         }
198         
199         if (version.equals(Constants.SCHEMA_VERSION_V1) && this.networkInputs.getAicNodeClli () == null) {
200                 throw new ValidationException ("aic-node-clli");
201         }
202         
203         if ((version.equals (Constants.SCHEMA_VERSION_V2) || version.equals (Constants.SCHEMA_VERSION_V3)) && (this.networkInputs.getAicCloudRegion () == null || this.networkInputs.getAicCloudRegion ().isEmpty())) {
204                 throw new ValidationException ("aic-cloud-region");
205         }
206         
207         if (version.equals(Constants.SCHEMA_VERSION_V3) && this.networkInputs.getServiceInstanceId () == null) {
208                 throw new ValidationException ("service-instance-id");
209         }
210
211         if (ActionType.CREATE.equals (action)) {
212             if (this.networkInputs.getTenantId () == null) {
213                 throw new ValidationException ("tenant-id");
214             }
215         }
216
217         
218         Object vpN = networkReq.getNetworkParams ();
219
220         if (vpN != null) {
221             Node node = (Node) vpN;
222             Document doc = node.getOwnerDocument ();
223             this.networkParams = domToStr (doc);
224         }
225
226         msoLogger.debug ("NetworkParams: " + this.networkParams);
227
228         msoLogger.debug ("Request valid");
229
230         // Rebuild the request string for BPEL to include request-id
231         rinfo.setRequestId (this.requestId);
232         networkReq.setRequestInfo (rinfo);
233
234         StringWriter stringWriter = new StringWriter ();
235         try {
236             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
237             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
238
239             // output pretty printed
240             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
241
242             jaxbMarshaller.marshal (networkReq, stringWriter);
243
244         } catch (JAXBException e) {
245             msoLogger.debug ("Exception: ", e);
246         }
247
248         this.requestXML = stringWriter.toString ().replace ("http://org.openecomp/mso/infra/network-request",
249                                                             "http://org.openecomp/mso/infra/vnf-request");
250         msoLogger.debug("REQUEST XML to BPEL: " + this.requestXML);
251
252     }
253
254     public void createRequestRecord (Status status) {
255
256         long startTime = System.currentTimeMillis ();
257
258         Session session = null;
259         try {
260
261             session = requestsDbSessionFactoryManager.getSessionFactory ().openSession ();
262             session.beginTransaction ();
263
264             InfraActiveRequests aq = new InfraActiveRequests ();
265             aq.setRequestId (requestId);
266
267             Timestamp startTimeStamp = new Timestamp (System.currentTimeMillis());
268             if (rinfo != null) {
269                 if (rinfo.getAction () != null) {
270                     aq.setAction (rinfo.getAction ().value ());
271                     aq.setRequestAction (RequestActionMap.getMappedRequestAction (rinfo.getAction ().value ()));
272                 }
273                 aq.setSource (rinfo.getSource ());
274             } else {
275                 // Set up mandatory parameters
276                 aq.setAction (NOT_PROVIDED);
277                 aq.setRequestAction (NOT_PROVIDED);
278             }
279
280             aq.setRequestBody (this.requestXML);
281             aq.setRequestScope (ModelType.network.name ());
282
283             if (networkInputs != null) {
284                 if (networkInputs.getNetworkId () != null) {
285                     aq.setVnfId (networkInputs.getNetworkId ());
286                 }
287                 if (networkInputs.getNetworkName () != null) {
288                     aq.setVnfName (networkInputs.getNetworkName ());
289                 }
290                 if (networkInputs.getNetworkType () != null) {
291                     aq.setVnfType (networkInputs.getNetworkType ());
292                 }
293                 if (networkInputs.getServiceInstanceId () != null) {
294                     aq.setServiceInstanceId (networkInputs.getServiceInstanceId ());
295                 }
296                 if (networkInputs.getServiceType () != null) {
297                     aq.setServiceType (networkInputs.getServiceType ());
298                 }
299                 if (networkInputs.getServiceId () != null) {
300                     aq.setServiceType (networkInputs.getServiceId ());
301                 }
302                 if (networkInputs.getAicNodeClli () != null) {
303                     aq.setAicNodeClli (networkInputs.getAicNodeClli ());
304                 }
305                 if (networkInputs.getTenantId () != null) {
306                     aq.setTenantId (networkInputs.getTenantId ());
307                 }
308                 if (networkInputs.getProvStatus () != null) {
309                     aq.setProvStatus (networkInputs.getProvStatus ());
310                 }
311
312             }
313             aq.setStartTime (startTimeStamp);
314             aq.setRequestStatus (status.toString ());
315             aq.setLastModifiedBy (Constants.MODIFIED_BY_APIHANDLER);
316             aq.setRequestType ("NETWORK");
317
318             if (networkParams != null) {
319                 msoLogger.debug ("Storing networkParams: " + networkParams);
320                 aq.setVnfParams (this.networkParams);
321             }
322
323             if ((status == Status.FAILED) || (status == Status.COMPLETE)) {
324                 aq.setStatusMessage (this.errorMessage);
325                 aq.setResponseBody (this.responseBody);
326
327                 Timestamp endTimeStamp = new Timestamp (System.currentTimeMillis());
328                 aq.setEndTime (endTimeStamp);                
329             } 
330             aq.setProgress (this.progress);
331             
332
333             msoLogger.debug ("About to insert a record");
334
335             session.save (aq);
336             session.getTransaction ().commit ();
337             session.close ();
338             msoLogger.recordMetricEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully", "RequestDB", "saveRequest", null);
339
340         } catch (Exception e) {
341                 msoLogger.error (MessageEnum.APIH_DB_INSERT_EXC, "", "", MsoLogger.ErrorCode.SchemaError, "Exception in createRequestRecord", e);
342             msoLogger.recordMetricEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, e.getMessage (), "RequestDB", "saveRequest", null);
343             if (session != null) {
344                 session.close ();
345             }
346             if (!status.equals (Status.FAILED)) {
347                 throw e;
348             }
349         }
350     }
351
352     public void updateFinalStatus (Status status) {
353         try {
354             (RequestsDatabase.getInstance()).updateInfraFinalStatus (requestId,
355                                                      status.toString (),
356                                                      this.errorMessage,
357                                                      this.progress,
358                                                      this.responseBody,
359                                                      Constants.MODIFIED_BY_APIHANDLER);
360         } catch (Exception e) {
361                 msoLogger.error (MessageEnum.APIH_DB_UPDATE_EXC, e.getMessage (), "", "", MsoLogger.ErrorCode.SchemaError, "Exception in updateFinalStatus");
362             msoLogger.debug ("Exception: ", e);
363         }
364     }
365
366     public Response buildResponse (int httpResponseCode, String errorCode, InfraActiveRequests inProgress) {
367         return buildResponseWithError (httpResponseCode, errorCode, inProgress, null);
368     }
369
370     public Response buildResponseWithError (int httpResponseCode,
371                                             String errorCode,
372                                             InfraActiveRequests inProgress,
373                                             String errorString) {
374
375         ObjectFactory beansObjectFactory = new ObjectFactory ();
376
377         NetworkRequest vr = beansObjectFactory.createNetworkRequest ();
378
379         RequestInfo ri = beansObjectFactory.createRequestInfo ();
380
381         ri.setRequestId (requestId);
382         ri.setRequestStatus (this.status);
383         ri.setAction (this.rinfo.getAction ());
384         ri.setSource (this.rinfo.getSource ());
385
386         String errorMsg = null;
387         if (errorCode != null) {
388             // If error code is actually an XML error response from BPEL, treat it specially:
389             if (!Messages.errors.containsKey (errorCode)) {
390                 if (errorCode.length () > 300) {
391                     errorMsg = errorCode.substring (0, 299);
392                 } else {
393                     errorMsg = errorCode;
394                 }
395
396             } else {
397
398                 if (inProgress == null) {
399                     if (errorCode.equals (ErrorNumbers.RECIPE_DOES_NOT_EXIST)) {
400                         errorMsg = String.format (Messages.errors.get (errorCode), "network", errorString);
401                     } else {
402                         errorMsg = String.format (Messages.errors.get (errorCode), errorString);
403                     }
404                 } else if (errorCode.equals (ErrorNumbers.LOCKED_CREATE_ON_THE_SAME_VNF_NAME_IN_PROGRESS)) {
405                     errorMsg = String.format (Messages.errors.get (errorCode),
406                                               "network",
407                                               inProgress.getVnfName (),
408                                               inProgress.getRequestStatus (),
409                                               "network");
410                 } else if (errorCode.equals (ErrorNumbers.LOCKED_SAME_ACTION_AND_VNF_ID)) {
411                     errorMsg = String.format (Messages.errors.get (errorCode),
412                                               "network",
413                                               inProgress.getVnfId (),
414                                               inProgress.getRequestStatus (),
415                                               inProgress.getAction (),
416                                               "network");
417                 }
418             }
419
420             ri.setStatusMessage (errorMsg);
421             this.errorMessage = errorMsg;
422         }
423         ri.setProgress ((int) this.progress);
424
425         Date startDate = new Date (this.startTime);
426         SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
427         String startTimeString = sdf.format (startDate);
428
429         ri.setStartTime (startTimeString);
430
431         vr.setRequestInfo (ri);
432         vr.setNetworkInputs (this.networkInputs);
433
434         StringWriter stringWriter = new StringWriter ();
435         try {
436             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
437             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
438             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
439
440             jaxbMarshaller.marshal (vr, stringWriter);
441
442         } catch (JAXBException e) {
443             msoLogger.debug ("Exception: ", e);
444         }
445
446         String response = stringWriter.toString ();
447
448         this.httpResponse = Integer.toString (httpResponseCode);
449         this.responseBody = response;
450
451         // Log the failed request into the MSO Requests database
452
453         return Response.status (httpResponseCode).entity (response).build ();
454
455     }
456
457     public Response buildResponseFailedValidation (int httpResponseCode, String exceptionMessage) {
458
459         ObjectFactory beansObjectFactory = new ObjectFactory ();
460         NetworkRequest vr = beansObjectFactory.createNetworkRequest ();
461
462         RequestInfo ri = beansObjectFactory.createRequestInfo ();
463         ri.setRequestId (requestId);
464
465         if (this.rinfo != null) {
466             if (this.rinfo.getAction () != null) {
467                 ri.setAction (this.rinfo.getAction ());
468             } else {
469                 ri.setAction (ActionType.NOT_PROVIDED);
470             }
471             if (this.rinfo.getSource () != null) {
472                 ri.setSource (this.rinfo.getSource ());
473             }
474         } else {
475             ri.setAction (ActionType.NOT_PROVIDED);
476         }
477
478         // Nothing more is expected for this request
479
480         String errorMsg = String.format (Messages.errors.get (ErrorNumbers.REQUEST_FAILED_SCHEMA_VALIDATION
481                                                               + "_service"),
482                                          exceptionMessage);
483         ri.setStatusMessage (errorMsg);
484         this.errorMessage = errorMsg;
485
486         ri.setProgress ((int) this.progress);
487         ri.setRequestStatus (RequestStatusType.FAILED);
488         Date startDate = new Date (this.startTime);
489         SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
490         String startTimeString = sdf.format (startDate);
491
492         ri.setStartTime (startTimeString);
493
494         vr.setRequestInfo (ri);
495         vr.setNetworkInputs (this.networkInputs);
496
497         StringWriter stringWriter = new StringWriter ();
498         try {
499             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
500             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
501
502             // output pretty printed
503             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
504
505             jaxbMarshaller.marshal (vr, stringWriter);
506
507         } catch (JAXBException e) {
508             msoLogger.debug ("Error marshalling", e);
509         }
510
511         String response = stringWriter.toString ();
512
513         this.httpResponse = Integer.toString (httpResponseCode);
514         this.responseBody = response;
515
516         return Response.status (httpResponseCode).entity (response).build ();
517     }
518
519     public String getRequestUri () {
520         return requestUri;
521     }
522
523     public void setRequestUri (String requestUri) {
524         this.requestUri = requestUri;
525     }
526
527     public NetworkInputs getNetworkInputs () {
528         return networkInputs;
529     }
530
531     public RequestInfo getRequestInfo () {
532         return rinfo;
533     }
534
535     public String getResponseBody () {
536         return responseBody;
537     }
538
539     public void setResponseBody (String responseBody) {
540         this.responseBody = responseBody;
541     }
542
543     public String getHttpResponse () {
544         return httpResponse;
545     }
546
547     public void setHttpResponse (String httpResponse) {
548         this.httpResponse = httpResponse;
549     }
550
551     public String getRequestId () {
552         return requestId;
553     }
554
555     public String getRequestXML () {
556         return requestXML;
557     }
558
559     public void setRequestXML (String requestXML) {
560         this.requestXML = requestXML;
561     }
562
563     public RequestStatusType getStatus () {
564         return status;
565     }
566
567     public void setStatus (RequestStatusType status) {
568         this.status = status;
569         switch (status) {
570         case FAILED:
571         case COMPLETE:
572                 this.progress = Constants.PROGRESS_REQUEST_COMPLETED;
573                 break;
574         case IN_PROGRESS:
575                 this.progress = Constants.PROGRESS_REQUEST_IN_PROGRESS;
576                 break;
577         }
578     }
579     
580     public String getServiceType () {
581         if (this.networkInputs.getServiceType () != null) 
582                 return this.networkInputs.getServiceType ();
583         if (this.networkInputs.getServiceId () != null) 
584                 return this.networkInputs.getServiceId ();
585         return null;
586     }
587
588     public static String domToStr (Document doc) {
589         if (doc == null) {
590             return null;
591         }
592
593         try {
594             StringWriter sw = new StringWriter ();
595             StreamResult sr = new StreamResult (sw);
596             TransformerFactory tf = TransformerFactory.newInstance ();
597             Transformer t = tf.newTransformer ();
598             t.setOutputProperty (OutputKeys.STANDALONE, "yes");
599             NodeList nl = doc.getDocumentElement ().getChildNodes ();
600             DOMSource source = null;
601             for (int x = 0; x < nl.getLength (); x++) {
602                 Node e = nl.item (x);
603                 if (e instanceof Element) {
604                     source = new DOMSource (e);
605                     break;
606                 }
607             }
608             if (source != null) {
609                 t.transform (source, sr);
610
611                 String s = sw.toString ();
612                 return s;
613             }
614
615             return null;
616
617         } catch (Exception e) {
618                 msoLogger.error (MessageEnum.APIH_DOM2STR_ERROR, "", "", MsoLogger.ErrorCode.DataError, "Exception in domToStr", e);
619         }
620         return null;
621     }
622 }