AT&T 1712 and 1802 release code
[so.git] / mso-api-handlers / mso-api-handler-infra / src / main / java / org / openecomp / mso / apihandlerinfra / tenantisolation / CloudOrchestration.java
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.tenantisolation;
22
23
24 import java.util.HashMap;
25
26 import javax.ws.rs.Consumes;
27 import javax.ws.rs.POST;
28 import javax.ws.rs.Path;
29 import javax.ws.rs.PathParam;
30 import javax.ws.rs.Produces;
31 import javax.ws.rs.core.MediaType;
32 import javax.ws.rs.core.Response;
33
34 import org.apache.http.HttpStatus;
35 import com.fasterxml.jackson.databind.ObjectMapper;
36 import org.openecomp.mso.apihandler.common.ErrorNumbers;
37 import org.openecomp.mso.apihandlerinfra.Constants;
38 import org.openecomp.mso.apihandlerinfra.MsoException;
39 import org.openecomp.mso.apihandlerinfra.Status;
40 import org.openecomp.mso.apihandlerinfra.tenantisolationbeans.Action;
41 import org.openecomp.mso.apihandlerinfra.tenantisolationbeans.OperationalEnvironment;
42 import org.openecomp.mso.apihandlerinfra.tenantisolationbeans.RequestReferences;
43 import org.openecomp.mso.apihandlerinfra.tenantisolationbeans.TenantSyncResponse;
44 import org.openecomp.mso.logger.MessageEnum;
45 import org.openecomp.mso.logger.MsoLogger;
46 import org.openecomp.mso.requestsdb.InfraActiveRequests;
47 import org.openecomp.mso.requestsdb.RequestsDatabase;
48 import org.openecomp.mso.utils.UUIDChecker;
49
50 import com.wordnik.swagger.annotations.Api;
51 import com.wordnik.swagger.annotations.ApiOperation;
52
53 @Path("/cloudResources")
54 @Api(value="/cloudResources",description="API Requests for cloud resources - Tenant Isolation")
55 public class CloudOrchestration {
56         
57         private static MsoLogger msoLogger = MsoLogger.getMsoLogger (MsoLogger.Catalog.APIH);
58         private TenantIsolationRunnable tenantIsolation = null;
59         private TenantIsolationRequest tenantIsolationRequest = null;
60         private RequestsDatabase requestsDatabase = null;
61         
62         @POST
63         @Path("/{version:[vV][1]}/operationalEnvironments")
64         @Consumes(MediaType.APPLICATION_JSON)
65         @Produces(MediaType.APPLICATION_JSON)
66         @ApiOperation(value="Create an Operational Environment",response=Response.class)
67         public Response createOperationEnvironment(String request, @PathParam("version") String version) {
68                 msoLogger.debug("Received request to Create Operational Environment");
69                 return cloudOrchestration(request, Action.create, null, version);
70         }
71         
72         @POST
73         @Path("/{version:[vV][1]}/operationalEnvironments/{operationalEnvironmentId}/activate")
74         @Consumes(MediaType.APPLICATION_JSON)
75         @Produces(MediaType.APPLICATION_JSON)
76         @ApiOperation(value="Activate an Operational Environment",response=Response.class)
77         public Response activateOperationEnvironment(String request, @PathParam("version") String version, @PathParam("operationalEnvironmentId") String operationalEnvironmentId) {
78                 msoLogger.debug("Received request to Activate an Operational Environment");
79                 HashMap<String, String> instanceIdMap = new HashMap<String,String>();
80                 instanceIdMap.put("operationalEnvironmentId", operationalEnvironmentId);
81                 return cloudOrchestration(request, Action.activate, instanceIdMap, version);
82         }
83         
84         @POST
85         @Path("/{version:[vV][1]}/operationalEnvironments/{operationalEnvironmentId}/deactivate")
86         @Consumes(MediaType.APPLICATION_JSON)
87         @Produces(MediaType.APPLICATION_JSON)
88         @ApiOperation(value="Deactivate an Operational Environment",response=Response.class)
89         public Response deactivateOperationEnvironment(String request, @PathParam("version") String version, @PathParam("operationalEnvironmentId") String operationalEnvironmentId) {
90                 msoLogger.debug("Received request to Deactivate an Operational Environment");
91                 HashMap<String, String> instanceIdMap = new HashMap<String,String>();
92                 instanceIdMap.put("operationalEnvironmentId", operationalEnvironmentId);
93                 return cloudOrchestration(request, Action.deactivate, instanceIdMap, version);
94         }
95         
96         
97         private Response cloudOrchestration(String requestJSON, Action action, HashMap<String, String> instanceIdMap, String version) {
98                 String requestId = UUIDChecker.generateUUID(msoLogger);
99                 long startTime = System.currentTimeMillis ();
100                 CloudOrchestrationRequest cor = null;
101                 Response response = null;
102                 getTenantIsolationRequest().setRequestId(requestId);
103                 
104                 try {
105                         cor = convertJsonToCloudOrchestrationRequest(requestJSON, action, startTime, cor);
106                 } catch(Exception e) {
107                         response = getTenantIsolationRequest().buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST, 
108                                                                                                                                                 MsoException.ServiceException,
109                                                                                                                                                 "Mapping of request to JSON object failed.  " + e.getMessage(),
110                                                                                                                                                 ErrorNumbers.SVC_BAD_PARAMETER, 
111                                                                                                                                                 null);
112                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
113                         return response;
114                 }
115                 
116                 try {
117                         getTenantIsolationRequest().parse(cor, instanceIdMap, action);
118                 } catch(Exception e) {
119                         msoLogger.debug ("Validation failed: ", e);
120                         if (getTenantIsolationRequest().getRequestId () != null) {
121                                 msoLogger.debug ("Logging failed message to the database");
122                                 getTenantIsolationRequest().createRequestRecord (Status.FAILED, action);
123                         }
124                         response = getTenantIsolationRequest().buildServiceErrorResponse(HttpStatus.SC_BAD_REQUEST, 
125                                                                                                                                                 MsoException.ServiceException,
126                                                                                                                                                 "Error parsing request.  " + e.getMessage(),
127                                                                                                                                                 ErrorNumbers.SVC_BAD_PARAMETER, null);
128                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
129                         return response;
130                 }
131                 
132                 String instanceName = cor.getRequestDetails().getRequestInfo().getInstanceName();
133                 String resourceType = cor.getRequestDetails().getRequestInfo().getResourceType().name();
134                 InfraActiveRequests dup = null;
135                 String messageAppend = null;
136                 try {
137                         dup = duplicateCheck(action, instanceIdMap, startTime, instanceName, resourceType);
138                         
139                         if(dup != null) {
140                                 messageAppend = "already has a request being worked with a status of " + dup.getRequestStatus() + " (RequestId - " + dup.getRequestId() + ").";
141                         }
142                 } catch(Exception e) {
143                         response = getTenantIsolationRequest().buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, 
144                                                                                                                                                 MsoException.ServiceException,
145                                                                                                                                                 e.getMessage(),
146                                                                                                                                                 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
147                                                                                                                                                 null) ;
148                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
149                         return response;
150                 }
151                 
152                 try {
153                         if(dup == null && (Action.activate.equals(action) || Action.deactivate.equals(action))) {
154                                 dup = getRequestsDatabase().checkVnfIdStatus(cor.getOperationalEnvironmentId());
155                                 if(dup != null) {
156                                         messageAppend = "OperationalEnvironmentId is not COMPLETED.";
157                                 }
158                         }
159                 } catch(Exception e) {
160                         response = getTenantIsolationRequest().buildServiceErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, 
161                                                                                                                                                         MsoException.ServiceException,
162                                                                                                                                                         e.getMessage(),
163                                                                                                                                                         ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
164                                                                                                                                                         null) ;
165                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
166                         return response;
167                 }
168                 
169                 if(dup != null) {
170                         String instance = null;
171                         if(instanceName != null){
172                                 instance = instanceName;
173                         }else{
174                                 instance = instanceIdMap.get(resourceType + "InstanceId");
175                         }
176                         String dupMessage =  "Error: Locked instance - This " + resourceType + " (" + instance + ") " + messageAppend + " The existing request must finish or be cleaned up before proceeding.";
177
178                         response = getTenantIsolationRequest().buildServiceErrorResponse(HttpStatus.SC_CONFLICT, 
179                                                                                                                                                 MsoException.ServiceException,
180                                                                                                                                                 dupMessage,
181                                                                                                                                                 ErrorNumbers.SVC_DETAILED_SERVICE_ERROR,
182                                                                                                                                                 null) ;
183
184                         msoLogger.warn (MessageEnum.APIH_DUPLICATE_FOUND, dupMessage, "", "", MsoLogger.ErrorCode.SchemaError, dupMessage);
185                         getTenantIsolationRequest().createRequestRecord (Status.FAILED, action);
186                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, dupMessage);
187                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
188                         return response;
189                 }
190                 
191                 String instanceId = null;
192                 try {
193                         if(instanceIdMap != null && instanceIdMap.get("operationalEnvironmentId") != null) {
194                                 instanceId = instanceIdMap.get("operationalEnvironmentId");
195                         } else {
196                                 instanceId = UUIDChecker.generateUUID(msoLogger);
197                                 getTenantIsolationRequest().setOperationalEnvironmentId(instanceId);
198                                 cor.setOperationalEnvironmentId(instanceId);
199                         }
200                         
201                         msoLogger.debug("Creating record in Request DB");
202                         getTenantIsolationRequest().createRequestRecord(Status.IN_PROGRESS, action);
203                 } catch(Exception e) {
204                         response = getTenantIsolationRequest().buildServiceErrorResponse (HttpStatus.SC_INTERNAL_SERVER_ERROR,
205                                                                                                                                                 MsoException.ServiceException,
206                                                                                                                                                 "Exception while creating record in DB " + e.getMessage(),
207                                                                                                                                                 ErrorNumbers.SVC_BAD_PARAMETER,
208                                                                                                                                                 null);
209                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
210                         return response;
211                 }
212                 
213                 try {
214                         OperationalEnvironment opEnv = cor.getRequestDetails().getRequestParameters().getOperationalEnvironmentType();
215                         String operationalEnvType = opEnv != null ? opEnv.name() : null;
216                         
217                         TenantIsolationRunnable runnable = getThread();
218                         runnable.setAction(action);
219                         runnable.setCor(cor);
220                         runnable.setOperationalEnvType(operationalEnvType);
221                         runnable.setRequestId(requestId);
222                         
223                         Thread thread = new Thread(runnable);
224                         thread.start();
225                 } catch(Exception e) {
226                         msoLogger.recordMetricEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating a new Thread", "APIH", null, null);
227                         response = getTenantIsolationRequest().buildServiceErrorResponse (HttpStatus.SC_INTERNAL_SERVER_ERROR,
228                                                                                                                                                 MsoException.ServiceException,
229                                                                                                                                                 "Failed creating a Thread " + e.getMessage (),
230                                                                                                                                                 ErrorNumbers.SVC_NO_SERVER_RESOURCES,
231                                                                                                                                                 null);
232                         getTenantIsolationRequest().updateFinalStatus (Status.FAILED);
233                         msoLogger.error (MessageEnum.APIH_GENERAL_EXCEPTION, Constants.MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.UnknownError, "Exception while creating a new Thread");
234                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, "Exception while creating a new Thread");
235                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
236                         return response;
237                 }
238                 
239                 try {
240                         String encodedValue  = new String(instanceId.getBytes("UTF-8"));
241                         msoLogger.debug ("InstanceId: " + instanceId + " encoded to " + encodedValue);
242                         
243                         TenantSyncResponse tenantResponse = new TenantSyncResponse();
244                         RequestReferences reqReference = new RequestReferences();
245                         reqReference.setInstanceId(encodedValue);
246                         reqReference.setRequestId(requestId);
247                         tenantResponse.setRequestReferences(reqReference);
248                         
249                         response = Response.ok(tenantResponse).build();
250                         
251                         msoLogger.debug ("Successful Sync response " + response.getEntity() + " with status code " + response.getStatus());
252                         
253                         return response;
254                 } catch(Exception e) {
255                         msoLogger.recordMetricEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while building sync response", "APIH", null, null);
256                         response = getTenantIsolationRequest().buildServiceErrorResponse (HttpStatus.SC_INTERNAL_SERVER_ERROR,
257                                                                                                                                                 MsoException.ServiceException,
258                                                                                                                                                 "Failed sending Sync Response " + e.getMessage (),
259                                                                                                                                                 ErrorNumbers.SVC_NO_SERVER_RESOURCES,
260                                                                                                                                                 null);
261                         getTenantIsolationRequest().updateFinalStatus (Status.FAILED);
262                         msoLogger.error (MessageEnum.APIH_GENERAL_EXCEPTION, Constants.MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.UnknownError, "Exception while sending sync Response");
263                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, "Exception while sending sync Response");
264                         msoLogger.debug ("End of the transaction, the final response is: " + (String) response.getEntity ());
265                         return response;
266                 }
267         }
268
269         private InfraActiveRequests duplicateCheck(Action action, HashMap<String, String> instanceIdMap, long startTime,
270                                                 String instanceName, String requestScope) throws Exception {
271                 InfraActiveRequests dup = null;
272                 try {
273                         dup = getRequestsDatabase().checkInstanceNameDuplicate (instanceIdMap, instanceName, requestScope);
274                 } catch (Exception e) {
275                         msoLogger.error (MessageEnum.APIH_DUPLICATE_CHECK_EXC, Constants.MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.DataError, "Error during duplicate check ", e);
276                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DBAccessError, "Error during duplicate check");
277                         throw new Exception(e);
278                 }
279                 return dup;
280         }
281         
282         private CloudOrchestrationRequest convertJsonToCloudOrchestrationRequest(String requestJSON, Action action, long startTime,
283                 CloudOrchestrationRequest cor) throws Exception {
284                 try{
285                         msoLogger.debug("Converting incoming JSON request to Object");
286                         ObjectMapper mapper = new ObjectMapper();
287                         cor = mapper.readValue(requestJSON, CloudOrchestrationRequest.class);
288                 } catch(Exception e){
289                         msoLogger.debug ("Mapping of request to JSON object failed : ", e);
290                         if (getTenantIsolationRequest().getRequestId () != null) {
291                                 msoLogger.debug ("Mapping of request to JSON object failed");
292                                 getTenantIsolationRequest().createRequestRecord (Status.FAILED, action);
293                         }
294                         msoLogger.error (MessageEnum.APIH_REQUEST_VALIDATION_ERROR, Constants.MSO_PROP_APIHANDLER_INFRA, "", "", MsoLogger.ErrorCode.SchemaError, requestJSON, e);
295                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, "Mapping of request to JSON object failed");
296                         throw new Exception(e);
297                 }
298                 return cor;
299         }
300         
301         public TenantIsolationRequest getTenantIsolationRequest() {
302                 if(tenantIsolationRequest == null) {
303                         tenantIsolationRequest = new TenantIsolationRequest();
304                 }
305                 return tenantIsolationRequest;
306         }
307
308         public void setTenantIsolationRequest(TenantIsolationRequest tenantIsolationRequest) {
309                 this.tenantIsolationRequest = tenantIsolationRequest;
310         }
311
312         public RequestsDatabase getRequestsDatabase() {
313                 if(requestsDatabase == null) {
314                         requestsDatabase = RequestsDatabase.getInstance();
315                 }
316                 return requestsDatabase;
317         }
318
319         public void setRequestsDatabase(RequestsDatabase requestsDatabase) {
320                 this.requestsDatabase = requestsDatabase;
321         }
322         
323         public TenantIsolationRunnable getThread() {
324                 if(tenantIsolation == null) {
325                         tenantIsolation = new TenantIsolationRunnable();
326                 }
327                 return tenantIsolation;
328         }
329
330         public void setThread(TenantIsolationRunnable thread) {
331                 this.tenantIsolation = thread;
332         }
333 }