2  * ============LICENSE_START=======================================================
 
   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
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  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=========================================================
 
  21 package org.openecomp.mso.apihandlerinfra;
 
  23 import java.io.StringReader;
 
  24 import java.io.StringWriter;
 
  25 import java.sql.Timestamp;
 
  26 import java.text.SimpleDateFormat;
 
  27 import java.util.Calendar;
 
  28 import java.util.Date;
 
  30 import javax.ws.rs.core.Response;
 
  31 import javax.xml.bind.JAXBContext;
 
  32 import javax.xml.bind.JAXBException;
 
  33 import javax.xml.bind.Marshaller;
 
  34 import javax.xml.bind.Unmarshaller;
 
  35 import javax.xml.transform.OutputKeys;
 
  36 import javax.xml.transform.Transformer;
 
  37 import javax.xml.transform.TransformerFactory;
 
  38 import javax.xml.transform.dom.DOMSource;
 
  39 import javax.xml.transform.sax.SAXSource;
 
  40 import javax.xml.transform.stream.StreamResult;
 
  42 import org.hibernate.Session;
 
  43 import org.w3c.dom.Document;
 
  44 import org.w3c.dom.Element;
 
  45 import org.w3c.dom.Node;
 
  46 import org.w3c.dom.NodeList;
 
  47 import org.xml.sax.InputSource;
 
  49 import org.openecomp.mso.apihandler.common.ErrorNumbers;
 
  50 import org.openecomp.mso.apihandler.common.ValidationException;
 
  51 import org.openecomp.mso.apihandlerinfra.networkbeans.ActionType;
 
  52 import org.openecomp.mso.apihandlerinfra.networkbeans.NetworkInputs;
 
  53 import org.openecomp.mso.apihandlerinfra.networkbeans.NetworkRequest;
 
  54 import org.openecomp.mso.apihandlerinfra.networkbeans.ObjectFactory;
 
  55 import org.openecomp.mso.apihandlerinfra.networkbeans.RequestInfo;
 
  56 import org.openecomp.mso.apihandlerinfra.networkbeans.RequestStatusType;
 
  57 import org.openecomp.mso.logger.MessageEnum;
 
  58 import org.openecomp.mso.logger.MsoLogger;
 
  59 import org.openecomp.mso.properties.MsoJavaProperties;
 
  60 import org.openecomp.mso.requestsdb.HibernateUtil;
 
  61 import org.openecomp.mso.requestsdb.InfraActiveRequests;
 
  62 import org.openecomp.mso.requestsdb.RequestsDatabase;
 
  64 public class NetworkMsoInfraRequest {
 
  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;
 
  80     private static MsoLogger msoLogger = MsoLogger.getMsoLogger (MsoLogger.Catalog.APIH);
 
  81     private static final String NOT_PROVIDED = "not provided";
 
  83     NetworkMsoInfraRequest (String requestId) {
 
  84         this.requestId = requestId;
 
  85         Calendar startTimeCalendar = Calendar.getInstance ();
 
  86         this.startTime = startTimeCalendar.getTimeInMillis ();
 
  87         MsoLogger.setLogContext (requestId, null);
 
  92     void parse (String reqXML, String version, MsoJavaProperties props) throws ValidationException {
 
  94         msoLogger.debug ("Validating the request");
 
  96         this.requestXML = reqXML;
 
  98         NetworkRequest networkReq = null;
 
  99         boolean isWrongRootElement = false;
 
 102             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
 
 103             Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller ();
 
 105             InputSource inputSource = new InputSource (new StringReader (reqXML));
 
 106             SAXSource source = new SAXSource (inputSource);
 
 108             if (reqXML.contains ("network-request") && !reqXML.contains ("vnf-request")) {
 
 109                 networkReq = jaxbUnmarshaller.unmarshal (source, NetworkRequest.class).getValue ();
 
 111                 isWrongRootElement = true;
 
 114         } catch (Exception e) {
 
 115                  msoLogger.error (MessageEnum.APIH_VNFREQUEST_VALIDATION_ERROR, "", "", MsoLogger.ErrorCode.DataError, "Exception when parsing reqXML", e);
 
 116             throw new ValidationException ("format for network request");
 
 119         if (isWrongRootElement) {
 
 120                 msoLogger.error (MessageEnum.APIH_REQUEST_VALIDATION_ERROR_REASON, "root element is not correct", "", "", MsoLogger.ErrorCode.DataError, "root element <network-request> expected");
 
 121             throw new ValidationException ("root element <network-request> expected");
 
 124         if (networkReq == null) {
 
 125             throw new ValidationException ("network-request");
 
 128         this.rinfo = networkReq.getRequestInfo ();
 
 130         if (this.rinfo == null) {
 
 131             throw new ValidationException ("request-info");
 
 134         action = this.rinfo.getAction ();
 
 135         if (action == null) {
 
 136             throw new ValidationException ("action");
 
 139         if (!InfraUtils.isActionAllowed (props, "network", version, action.value ())) {
 
 140                 throw new ValidationException ("action allowable for version " + version + " of network request");              
 
 143         this.networkInputs = networkReq.getNetworkInputs ();
 
 144         if (this.networkInputs == null) {
 
 145             throw new ValidationException ("network-inputs");
 
 148         // Verify that the elements correspond to the version
 
 150         if (version.equals(Constants.SCHEMA_VERSION_V1)) {
 
 151                         if (this.networkInputs.getBackoutOnFailure() != null || this.networkInputs.getAicCloudRegion() != null ||
 
 152                                         this.networkInputs.getServiceInstanceId() != null) {
 
 153                                 throw new ValidationException ("format for v1 version of network request");
 
 156         else if (version.equals(Constants.SCHEMA_VERSION_V2)) {
 
 157                         if (this.networkInputs.getServiceType() != null || this.networkInputs.getAicNodeClli() != null ||
 
 158                                         this.networkInputs.getServiceInstanceId() != null) {
 
 159                                 throw new ValidationException ("format for v2 version of network request");
 
 162         else if (version.equals(Constants.SCHEMA_VERSION_V3)) {
 
 163                 if (this.networkInputs.getServiceType() != null || this.networkInputs.getAicNodeClli() != null) {
 
 164                         throw new ValidationException ("format for v3 version of network request");
 
 171                 if (this.networkInputs.getNetworkId () == null) {
 
 172                     throw new ValidationException ("network-id");
 
 179         if (ActionType.CREATE.equals (action) && this.networkInputs.getNetworkName () == null) {
 
 180             throw new ValidationException ("network-name");
 
 183         if (this.networkInputs.getNetworkType () == null) {
 
 184             throw new ValidationException ("network-type");
 
 187         if (!version.equals(Constants.SCHEMA_VERSION_V1) && this.networkInputs.getServiceId () == null) {
 
 188                 throw new ValidationException ("service-id ");
 
 191         if (this.networkInputs.getServiceType () != null && this.networkInputs.getServiceId () != null) {
 
 192                 throw new ValidationException ("service-type or service-id ");
 
 195         if (version.equals(Constants.SCHEMA_VERSION_V1) && this.networkInputs.getAicNodeClli () == null) {
 
 196                 throw new ValidationException ("aic-node-clli");
 
 199         if ((version.equals (Constants.SCHEMA_VERSION_V2) || version.equals (Constants.SCHEMA_VERSION_V3)) && (this.networkInputs.getAicCloudRegion () == null || this.networkInputs.getAicCloudRegion ().isEmpty())) {
 
 200                 throw new ValidationException ("aic-cloud-region");
 
 203         if (version.equals(Constants.SCHEMA_VERSION_V3) && this.networkInputs.getServiceInstanceId () == null) {
 
 204                 throw new ValidationException ("service-instance-id");
 
 207         if (ActionType.CREATE.equals (action)) {
 
 208             if (this.networkInputs.getTenantId () == null) {
 
 209                 throw new ValidationException ("tenant-id");
 
 214         Object vpN = networkReq.getNetworkParams ();
 
 217             Node node = (Node) vpN;
 
 218             Document doc = node.getOwnerDocument ();
 
 219             this.networkParams = domToStr (doc);
 
 222         msoLogger.debug ("NetworkParams: " + this.networkParams);
 
 224         msoLogger.debug ("Request valid");
 
 226         // Rebuild the request string for BPEL to include request-id
 
 227         rinfo.setRequestId (this.requestId);
 
 228         networkReq.setRequestInfo (rinfo);
 
 230         StringWriter stringWriter = new StringWriter ();
 
 232             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
 
 233             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
 
 235             // output pretty printed
 
 236             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
 238             jaxbMarshaller.marshal (networkReq, stringWriter);
 
 240         } catch (JAXBException e) {
 
 241             msoLogger.debug ("Exception: ", e);
 
 244         this.requestXML = stringWriter.toString ().replace ("http://ecomp.att.com/mso/infra/network-request",
 
 245                                                             "http://ecomp.att.com/mso/infra/vnf-request");
 
 246         msoLogger.debug("REQUEST XML to BPEL: " + this.requestXML);
 
 250     public void createRequestRecord (Status status) {
 
 252         long startTime = System.currentTimeMillis ();
 
 254         Session session = null;
 
 257             session = HibernateUtil.getSessionFactory ().openSession ();
 
 258             session.beginTransaction ();
 
 260             InfraActiveRequests aq = new InfraActiveRequests ();
 
 261             aq.setRequestId (requestId);
 
 263             Timestamp startTimeStamp = new Timestamp (Calendar.getInstance ().getTimeInMillis ());
 
 265                 if (rinfo.getAction () != null) {
 
 266                     aq.setAction (rinfo.getAction ().value ());
 
 267                     aq.setRequestAction (RequestActionMap.getMappedRequestAction (rinfo.getAction ().value ()));
 
 269                 aq.setSource (rinfo.getSource ());
 
 271                 // Set up mandatory parameters
 
 272                 aq.setAction (NOT_PROVIDED);
 
 273                 aq.setRequestAction (NOT_PROVIDED);
 
 276             aq.setRequestBody (this.requestXML);
 
 277             aq.setRequestScope (ModelType.network.name ());
 
 279             if (networkInputs != null) {
 
 280                 if (networkInputs.getNetworkId () != null) {
 
 281                     aq.setVnfId (networkInputs.getNetworkId ());
 
 283                 if (networkInputs.getNetworkName () != null) {
 
 284                     aq.setVnfName (networkInputs.getNetworkName ());
 
 286                 if (networkInputs.getNetworkType () != null) {
 
 287                     aq.setVnfType (networkInputs.getNetworkType ());
 
 289                 if (networkInputs.getServiceInstanceId () != null) {
 
 290                     aq.setServiceInstanceId (networkInputs.getServiceInstanceId ());
 
 292                 if (networkInputs.getServiceType () != null) {
 
 293                     aq.setServiceType (networkInputs.getServiceType ());
 
 295                 if (networkInputs.getServiceId () != null) {
 
 296                     aq.setServiceType (networkInputs.getServiceId ());
 
 298                 if (networkInputs.getAicNodeClli () != null) {
 
 299                     aq.setAicNodeClli (networkInputs.getAicNodeClli ());
 
 301                 if (networkInputs.getTenantId () != null) {
 
 302                     aq.setTenantId (networkInputs.getTenantId ());
 
 304                 if (networkInputs.getProvStatus () != null) {
 
 305                     aq.setProvStatus (networkInputs.getProvStatus ());
 
 309             aq.setStartTime (startTimeStamp);
 
 310             aq.setRequestStatus (status.toString ());
 
 311             aq.setLastModifiedBy (Constants.MODIFIED_BY_APIHANDLER);
 
 312             aq.setRequestType ("NETWORK");
 
 314             if (networkParams != null) {
 
 315                 msoLogger.debug ("Storing networkParams: " + networkParams);
 
 316                 aq.setVnfParams (this.networkParams);
 
 319             if ((status == Status.FAILED) || (status == Status.COMPLETE)) {
 
 320                 aq.setStatusMessage (this.errorMessage);
 
 321                 aq.setResponseBody (this.responseBody);
 
 323                 Calendar endTime = Calendar.getInstance ();
 
 324                 Timestamp endTimeStamp = new Timestamp (endTime.getTimeInMillis ());
 
 325                 aq.setEndTime (endTimeStamp);                
 
 327             aq.setProgress (this.progress);
 
 330             msoLogger.debug ("About to insert a record");
 
 333             session.getTransaction ().commit ();
 
 335             msoLogger.recordMetricEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully", "RequestDB", "saveRequest", null);
 
 337         } catch (Exception e) {
 
 338                 msoLogger.error (MessageEnum.APIH_DB_INSERT_EXC, "", "", MsoLogger.ErrorCode.SchemaError, "Exception in createRequestRecord", e);
 
 339             msoLogger.recordMetricEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, e.getMessage (), "RequestDB", "saveRequest", null);
 
 340             if (session != null) {
 
 343             if (!status.equals (Status.FAILED)) {
 
 349     public void updateFinalStatus (Status status) {
 
 351             RequestsDatabase.updateInfraFinalStatus (requestId,
 
 356                                                      Constants.MODIFIED_BY_APIHANDLER);
 
 357         } catch (Exception e) {
 
 358                 msoLogger.error (MessageEnum.APIH_DB_UPDATE_EXC, e.getMessage (), "", "", MsoLogger.ErrorCode.SchemaError, "Exception in updateFinalStatus");
 
 359             msoLogger.debug ("Exception: ", e);
 
 363     public Response buildResponse (int httpResponseCode, String errorCode, InfraActiveRequests inProgress) {
 
 364         return buildResponseWithError (httpResponseCode, errorCode, inProgress, null);
 
 367     public Response buildResponseWithError (int httpResponseCode,
 
 369                                             InfraActiveRequests inProgress,
 
 370                                             String errorString) {
 
 372         ObjectFactory beansObjectFactory = new ObjectFactory ();
 
 374         NetworkRequest vr = beansObjectFactory.createNetworkRequest ();
 
 376         RequestInfo ri = beansObjectFactory.createRequestInfo ();
 
 378         ri.setRequestId (requestId);
 
 379         ri.setRequestStatus (this.status);
 
 380         ri.setAction (this.rinfo.getAction ());
 
 381         ri.setSource (this.rinfo.getSource ());
 
 383         String errorMsg = null;
 
 384         if (errorCode != null) {
 
 385             // If error code is actually an XML error response from BPEL, treat it specially:
 
 386             if (!Messages.errors.containsKey (errorCode)) {
 
 387                 if (errorCode.length () > 300) {
 
 388                     errorMsg = errorCode.substring (0, 299);
 
 390                     errorMsg = errorCode;
 
 395                 if (inProgress == null) {
 
 396                     if (errorCode.equals (ErrorNumbers.RECIPE_DOES_NOT_EXIST)) {
 
 397                         errorMsg = String.format (Messages.errors.get (errorCode), "network", errorString);
 
 399                         errorMsg = String.format (Messages.errors.get (errorCode), errorString);
 
 401                 } else if (errorCode.equals (ErrorNumbers.LOCKED_CREATE_ON_THE_SAME_VNF_NAME_IN_PROGRESS)) {
 
 402                     errorMsg = String.format (Messages.errors.get (errorCode),
 
 404                                               inProgress.getVnfName (),
 
 405                                               inProgress.getRequestStatus (),
 
 407                 } else if (errorCode.equals (ErrorNumbers.LOCKED_SAME_ACTION_AND_VNF_ID)) {
 
 408                     errorMsg = String.format (Messages.errors.get (errorCode),
 
 410                                               inProgress.getVnfId (),
 
 411                                               inProgress.getRequestStatus (),
 
 412                                               inProgress.getAction (),
 
 417             ri.setStatusMessage (errorMsg);
 
 418             this.errorMessage = errorMsg;
 
 420         ri.setProgress ((int) this.progress);
 
 422         Date startDate = new Date (this.startTime);
 
 423         SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
 
 424         String startTimeString = sdf.format (startDate);
 
 426         ri.setStartTime (startTimeString);
 
 428         vr.setRequestInfo (ri);
 
 429         vr.setNetworkInputs (this.networkInputs);
 
 431         StringWriter stringWriter = new StringWriter ();
 
 433             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
 
 434             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
 
 435             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
 437             jaxbMarshaller.marshal (vr, stringWriter);
 
 439         } catch (JAXBException e) {
 
 440             msoLogger.debug ("Exception: ", e);
 
 443         String response = stringWriter.toString ();
 
 445         this.httpResponse = Integer.toString (httpResponseCode);
 
 446         this.responseBody = response;
 
 448         // Log the failed request into the MSO Requests database
 
 450         return Response.status (httpResponseCode).entity (response).build ();
 
 454     public Response buildResponseFailedValidation (int httpResponseCode, String exceptionMessage) {
 
 456         ObjectFactory beansObjectFactory = new ObjectFactory ();
 
 457         NetworkRequest vr = beansObjectFactory.createNetworkRequest ();
 
 459         RequestInfo ri = beansObjectFactory.createRequestInfo ();
 
 460         ri.setRequestId (requestId);
 
 462         if (this.rinfo != null) {
 
 463             if (this.rinfo.getAction () != null) {
 
 464                 ri.setAction (this.rinfo.getAction ());
 
 466                 ri.setAction (ActionType.NOT_PROVIDED);
 
 468             if (this.rinfo.getSource () != null) {
 
 469                 ri.setSource (this.rinfo.getSource ());
 
 472             ri.setAction (ActionType.NOT_PROVIDED);
 
 475         // Nothing more is expected for this request
 
 477         String errorMsg = String.format (Messages.errors.get (ErrorNumbers.REQUEST_FAILED_SCHEMA_VALIDATION
 
 480         ri.setStatusMessage (errorMsg);
 
 481         this.errorMessage = errorMsg;
 
 483         ri.setProgress ((int) this.progress);
 
 484         ri.setRequestStatus (RequestStatusType.FAILED);
 
 485         Date startDate = new Date (this.startTime);
 
 486         SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
 
 487         String startTimeString = sdf.format (startDate);
 
 489         ri.setStartTime (startTimeString);
 
 491         vr.setRequestInfo (ri);
 
 492         vr.setNetworkInputs (this.networkInputs);
 
 494         StringWriter stringWriter = new StringWriter ();
 
 496             JAXBContext jaxbContext = JAXBContext.newInstance (NetworkRequest.class);
 
 497             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
 
 499             // output pretty printed
 
 500             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
 502             jaxbMarshaller.marshal (vr, stringWriter);
 
 504         } catch (JAXBException e) {
 
 505             msoLogger.debug ("Error marshalling", e);
 
 508         String response = stringWriter.toString ();
 
 510         this.httpResponse = Integer.toString (httpResponseCode);
 
 511         this.responseBody = response;
 
 513         return Response.status (httpResponseCode).entity (response).build ();
 
 516     public String getRequestUri () {
 
 520     public void setRequestUri (String requestUri) {
 
 521         this.requestUri = requestUri;
 
 524     public NetworkInputs getNetworkInputs () {
 
 525         return networkInputs;
 
 528     public RequestInfo getRequestInfo () {
 
 532     public String getResponseBody () {
 
 536     public void setResponseBody (String responseBody) {
 
 537         this.responseBody = responseBody;
 
 540     public String getHttpResponse () {
 
 544     public void setHttpResponse (String httpResponse) {
 
 545         this.httpResponse = httpResponse;
 
 548     public String getRequestId () {
 
 552     public String getRequestXML () {
 
 556     public void setRequestXML (String requestXML) {
 
 557         this.requestXML = requestXML;
 
 560     public RequestStatusType getStatus () {
 
 564     public void setStatus (RequestStatusType status) {
 
 565         this.status = status;
 
 569                 this.progress = Constants.PROGRESS_REQUEST_COMPLETED;
 
 572                 this.progress = Constants.PROGRESS_REQUEST_IN_PROGRESS;
 
 577     public String getServiceType () {
 
 578         if (this.networkInputs.getServiceType () != null) 
 
 579                 return this.networkInputs.getServiceType ();
 
 580         if (this.networkInputs.getServiceId () != null) 
 
 581                 return this.networkInputs.getServiceId ();
 
 585     public static String domToStr (Document doc) {
 
 591             StringWriter sw = new StringWriter ();
 
 592             StreamResult sr = new StreamResult (sw);
 
 593             TransformerFactory tf = TransformerFactory.newInstance ();
 
 594             Transformer t = tf.newTransformer ();
 
 595             t.setOutputProperty (OutputKeys.STANDALONE, "yes");
 
 596             NodeList nl = doc.getDocumentElement ().getChildNodes ();
 
 597             DOMSource source = null;
 
 598             for (int x = 0; x < nl.getLength (); x++) {
 
 599                 Node e = nl.item (x);
 
 600                 if (e instanceof Element) {
 
 601                     source = new DOMSource (e);
 
 605             if (source != null) {
 
 606                 t.transform (source, sr);
 
 608                 String s = sw.toString ();
 
 614         } catch (Exception e) {
 
 615                 msoLogger.error (MessageEnum.APIH_DOM2STR_ERROR, "", "", MsoLogger.ErrorCode.DataError, "Exception in domToStr", e);