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