Replaced all tabs with spaces in java and pom.xml
[so.git] / adapters / mso-openstack-adapters / src / main / java / org / onap / so / adapters / vnf / VnfAdapterRestV2.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * OPENECOMP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (C) 2018 IBM.
8  * Modifications Copyright (c) 2019 Samsung
9  * ================================================================================
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  * ============LICENSE_END=========================================================
22  */
23
24 package org.onap.so.adapters.vnf;
25
26
27 import java.util.Map;
28 import javax.inject.Provider;
29 import javax.ws.rs.Consumes;
30 import javax.ws.rs.DELETE;
31 import javax.ws.rs.GET;
32 import javax.ws.rs.POST;
33 import javax.ws.rs.PUT;
34 import javax.ws.rs.Path;
35 import javax.ws.rs.PathParam;
36 import javax.ws.rs.Produces;
37 import javax.ws.rs.QueryParam;
38 import javax.ws.rs.core.GenericEntity;
39 import javax.ws.rs.core.MediaType;
40 import javax.ws.rs.core.Response;
41 import javax.xml.ws.Holder;
42 import org.apache.http.HttpStatus;
43 import org.onap.so.adapters.vnf.exceptions.VnfException;
44 import org.onap.so.adapters.vnfrest.CreateVfModuleRequest;
45 import org.onap.so.adapters.vnfrest.CreateVfModuleResponse;
46 import org.onap.so.adapters.vnfrest.DeleteVfModuleRequest;
47 import org.onap.so.adapters.vnfrest.DeleteVfModuleResponse;
48 import org.onap.so.adapters.vnfrest.QueryVfModuleResponse;
49 import org.onap.so.adapters.vnfrest.RollbackVfModuleRequest;
50 import org.onap.so.adapters.vnfrest.RollbackVfModuleResponse;
51 import org.onap.so.adapters.vnfrest.UpdateVfModuleRequest;
52 import org.onap.so.adapters.vnfrest.UpdateVfModuleResponse;
53 import org.onap.so.adapters.vnfrest.VfModuleExceptionResponse;
54 import org.onap.so.adapters.vnfrest.VfModuleRollback;
55 import org.onap.so.entity.MsoRequest;
56 import org.onap.so.logger.ErrorCode;
57 import org.onap.so.logger.MessageEnum;
58 import org.onap.so.openstack.beans.VnfRollback;
59 import org.onap.so.openstack.beans.VnfStatus;
60 import org.onap.so.openstack.exceptions.MsoExceptionCategory;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63 import org.springframework.beans.factory.annotation.Autowired;
64 import org.springframework.stereotype.Component;
65 import io.swagger.annotations.Api;
66 import io.swagger.annotations.ApiOperation;
67 import io.swagger.annotations.ApiParam;
68 import io.swagger.annotations.ApiResponse;
69 import io.swagger.annotations.ApiResponses;
70
71 /**
72  * This class services calls to the REST interface for VF Modules (http://host:port/vnfs/rest/v2/vnfs) Both XML and JSON
73  * can be produced/consumed. Set Accept: and Content-Type: headers appropriately. XML is the default. For testing, call
74  * with cloudSiteId = ___TESTING___ To test exceptions, also set tenantId = ___TESTING___
75  *
76  * V2 incorporates run-time selection of sub-orchestrator implementation (Heat or Cloudify) based on the target cloud.
77  */
78 @Path("/v2/vnfs")
79 @Api(value = "/v2/vnfs", description = "root of vnf adapters restful web service v2")
80 @Component
81 public class VnfAdapterRestV2 {
82     private static Logger logger = LoggerFactory.getLogger(VnfAdapterRestV2.class);
83     private static final String TESTING_KEYWORD = "___TESTING___";
84     private static final String RESP = ", resp=";
85
86     @Autowired
87     private VnfAdapterRestUtils vnfAdapterRestUtils;
88
89     @Autowired
90     private Provider<BpelRestClient> bpelRestClientProvider;
91
92     /*
93      * URL:http://localhost:8080/vnfs/rest/v2/vnfs/<aaivnfid>/vf-modules/<aaimodid> REQUEST: {"deleteVfModuleRequest":
94      * {"cloudSiteId": "DAN", "tenantId": "214b428a1f554c02935e66330f6a5409", "vnfId": "somevnfid", "vfModuleId":
95      * "somemodid", "vfModuleStackId": "4e567676-e266-4594-a3a6-131c8a2baf73", "messageId": "ra.1", "notificationUrl":
96      * "http://localhost:8089/vnfmock", "skipAAI": true, "msoRequest": { "requestId": "ra1", "serviceInstanceId": "sa1"
97      * }} }
98      */
99     @DELETE
100     @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}")
101     @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
102     @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
103     @ApiOperation(value = "DeleteVfModule", response = Response.class,
104             notes = "Delete an existing vnfModule, DeleteVfModuleRequest JSON is required")
105     @ApiResponses({@ApiResponse(code = 200, message = "vnfModule has been successfully deleted"),
106             @ApiResponse(code = 202, message = "delete vnfModule request has been accepted (async only)"),
107             @ApiResponse(code = 500, message = "delete vnfModule failed, examine entity object for details")})
108     public Response deleteVfModule(
109             @ApiParam(value = "aaiVnfId", required = true) @PathParam("aaiVnfId") String aaiVnfId,
110             @ApiParam(value = "aaiVfModuleId", required = true) @PathParam("aaiVfModuleId") String aaiVfModuleId,
111             @ApiParam(value = "mode", required = true) @QueryParam("mode") String mode,
112             @ApiParam(value = "DeleteVfModuleRequest", required = true) final DeleteVfModuleRequest req) {
113         logger.debug("Delete VfModule enter: " + req.toJsonString());
114         if (aaiVnfId == null || !aaiVnfId.equals(req.getVnfId())) {
115             logger.debug("Req rejected - aaiVnfId not provided or doesn't match URL");
116             return Response.status(HttpStatus.SC_BAD_REQUEST).type(MediaType.TEXT_PLAIN)
117                     .entity("vnfid in URL does not match content").build();
118         }
119         if (aaiVfModuleId == null || !aaiVfModuleId.equals(req.getVfModuleId())) {
120             logger.debug("Req rejected - aaiVfModuleId not provided or doesn't match URL");
121             return Response.status(HttpStatus.SC_BAD_REQUEST).type(MediaType.TEXT_PLAIN)
122                     .entity("vfModuleId in URL does not match content").build();
123         }
124
125         DeleteVfModuleTask task = new DeleteVfModuleTask(req, mode);
126         if (req.isSynchronous()) {
127             // This is a synchronous request
128             task.run();
129             return Response.status(task.getStatusCode()).entity(task.getGenericEntityResponse()).build();
130         } else {
131             // This is an asynchronous request
132             try {
133                 Thread t1 = new Thread(task);
134                 t1.start();
135             } catch (Exception e) {
136                 // problem handling delete, send generic failure as sync resp to caller
137                 logger.error("{} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), "deleteVfModule",
138                         ErrorCode.BusinessProcesssError.getValue(), "Exception in deleteVfModule", e);
139                 return Response.serverError().build();
140             }
141             // send sync response (ACK) to caller
142             logger.debug("deleteVNFVolumes exit");
143             return Response.status(HttpStatus.SC_ACCEPTED).build();
144         }
145     }
146
147     public class DeleteVfModuleTask implements Runnable {
148         private final DeleteVfModuleRequest req;
149         private DeleteVfModuleResponse response = null;
150         private VfModuleExceptionResponse eresp = null;
151         private boolean sendxml;
152         private String mode;
153
154         public DeleteVfModuleTask(DeleteVfModuleRequest req, String mode) {
155             this.req = req;
156             this.sendxml = true; // can be set with a field or header later
157             this.mode = mode;
158         }
159
160         public int getStatusCode() {
161             return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
162         }
163
164         public Object getGenericEntityResponse() {
165             return (response != null) ? new GenericEntity<DeleteVfModuleResponse>(response) {}
166                     : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
167         }
168
169         private String getResponse() {
170             if (response != null) {
171                 return sendxml ? response.toXmlString() : response.toJsonString();
172             } else {
173                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
174             }
175         }
176
177         @Override
178         public void run() {
179             try {
180                 String cloudsite = req.getCloudSiteId();
181                 Holder<Map<String, String>> outputs = new Holder<Map<String, String>>();
182                 if (cloudsite != null && !cloudsite.equals(TESTING_KEYWORD)) {
183                     // vnfAdapter.deleteVnf (req.getCloudSiteId(), req.getTenantId(), req.getVfModuleStackId(),
184                     // req.getMsoRequest());
185                     // Support different Adapter Implementations
186                     MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsite);
187                     adapter.deleteVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
188                             req.getVfModuleStackId(), req.getMsoRequest(), outputs);
189                 }
190                 response = new DeleteVfModuleResponse(req.getVnfId(), req.getVfModuleId(), Boolean.TRUE,
191                         req.getMessageId(), outputs.value);
192             } catch (VnfException e) {
193                 logger.error("{} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(),
194                         ErrorCode.BusinessProcesssError.getValue(), "VnfException - " + "Delete VNF Module", e);
195                 eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE,
196                         req.getMessageId());
197             }
198             if (!req.isSynchronous()) {
199                 BpelRestClient bpelClient = bpelRestClientProvider.get();
200                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
201             }
202             logger.debug("Delete vfModule exit: code=" + getStatusCode() + RESP + getResponse());
203         }
204     }
205
206     /*
207      * URL:http://localhost:8080/vnfs/rest/v2/vnfs/<aaiVnfId>/vf-modules/<aaiVfModuleId>?cloudSiteId=DAN&tenantId=
208      * vfModule?&skipAAI=TRUE&msoRequest.requestId=ra1&msoRequest.serviceInstanceId=si1&vfModuleName=T2N2S1 RESP:
209      * {"queryVfModuleResponse": { "vfModuleId": "AvfmodId", "vfModuleOutputs": {"entry": { "key":
210      * "server_private_ip_1", "value": "10.100.1.25" }}, "vfModuleStackId":
211      * "RaaVnf1/abfa8a6d-feb1-40af-aea3-109403b1cf6b", "vnfId": "AvnfID", "vnfStatus": "ACTIVE" }}
212      */
213     @GET
214     @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}")
215     @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
216     @ApiOperation(value = "QueryVfModule", response = Response.class, notes = "Query an existing vnfModule")
217     @ApiResponses({@ApiResponse(code = 200, message = "vnfModule has been successfully queried"),
218             @ApiResponse(code = 500, message = "query vnfModule failed, examine entity object for details")})
219     public Response queryVfModule(@ApiParam(value = "aaiVnfId", required = true) @PathParam("aaiVnfId") String aaiVnfId,
220             @ApiParam(value = "aaiVfModuleId", required = true) @PathParam("aaiVfModuleId") String aaiVfModuleId,
221             @ApiParam(value = "cloudSiteId", required = true) @QueryParam("cloudSiteId") String cloudSiteId,
222             @ApiParam(value = "cloudOwner", required = true) @QueryParam("cloudOwner") String cloudOwner,
223             @ApiParam(value = "tenantId", required = true) @QueryParam("tenantId") String tenantId,
224             @ApiParam(value = "vfModuleName", required = true) @QueryParam("vfModuleName") String vfModuleName, // RAA?
225                                                                                                                 // Id in
226                                                                                                                 // doc
227             @ApiParam(value = "skipAAI", required = true) @QueryParam("skipAAI") Boolean skipAAI,
228             @ApiParam(value = "msoRequest.requestId",
229                     required = true) @QueryParam("msoRequest.requestId") String requestId,
230             @ApiParam(value = "msoRequest.serviceInstanceId",
231                     required = true) @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId,
232             @ApiParam(value = "mode", required = true) @QueryParam("mode") String mode) {
233         // This request responds synchronously only
234         logger.debug("Query vfModule enter:" + vfModuleName);
235         MsoRequest msoRequest = new MsoRequest(requestId, serviceInstanceId);
236
237         try {
238             int respStatus = HttpStatus.SC_OK;
239             QueryVfModuleResponse qryResp = new QueryVfModuleResponse(aaiVnfId, aaiVfModuleId, null, null, null);
240             Holder<Boolean> vnfExists = new Holder<Boolean>();
241             Holder<String> vfModuleId = new Holder<String>();
242             Holder<VnfStatus> status = new Holder<VnfStatus>();
243             Holder<Map<String, String>> outputs = new Holder<Map<String, String>>();
244
245             // Support different Adapter Implementations
246             MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudSiteId);
247             adapter.queryVnf(cloudSiteId, cloudOwner, tenantId, vfModuleName, msoRequest, vnfExists, vfModuleId, status,
248                     outputs);
249
250             if (!vnfExists.value) {
251                 logger.debug("vfModule not found");
252                 respStatus = HttpStatus.SC_NOT_FOUND;
253             } else {
254                 logger.debug("vfModule found" + vfModuleId.value + ", status=" + status.value);
255                 qryResp.setVfModuleId(vfModuleId.value);
256                 qryResp.setVnfStatus(status.value);
257                 qryResp.setVfModuleOutputs(outputs.value);
258             }
259             logger.debug("Query vfModule exit");
260             return Response.status(respStatus).entity(new GenericEntity<QueryVfModuleResponse>(qryResp) {}).build();
261         } catch (VnfException e) {
262             logger.error("{} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, "queryVfModule",
263                     ErrorCode.BusinessProcesssError.getValue(), "VnfException - queryVfModule", e);
264             VfModuleExceptionResponse excResp =
265                     new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.FALSE, null);
266             return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR)
267                     .entity(new GenericEntity<VfModuleExceptionResponse>(excResp) {}).build();
268         }
269     }
270
271     /*
272      * URL: http://localhost:8080/vnfs/rest/v2/vnfs/<aaivnfid>/vf-modules REQUEST: {"createVfModuleRequest":
273      * {"cloudSiteId": "DAN", "tenantId": "214b428a1f554c02935e66330f6a5409", "vnfId": "somevnfid", "vfModuleId":
274      * "somemodid", "vfModuleName": "RaaVnf1", "vnfType": "ApacheVnf", "vfModuleParams": {"entry": [ {"key":
275      * "network_id", "value": "59ed7b41-2983-413f-ba93-e7d437433916"}, {"key": "subnet_id", "value":
276      * "086c9298-5c57-49b7-bb2b-6fd5730c5d92"}, {"key": "server_name_0", "value": "RaaVnf1"} ]}, "failIfExists": true,
277      * "messageId": "ra.1", "notificationUrl": "http://localhost:8089/vnfmock", "skipAAI": true, "msoRequest": {
278      * "requestId": "ra1", "serviceInstanceId": "sa1" }} }
279      */
280     @POST
281     @Path("{aaiVnfId}/vf-modules")
282     @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
283     @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
284     @ApiOperation(value = "CreateVfModule", response = Response.class, notes = "Create a vnfModule")
285     @ApiResponses({@ApiResponse(code = 200, message = "vnfModule has been successfully created"),
286             @ApiResponse(code = 202, message = "create vnfModule request has been successfully accepted (async only)"),
287             @ApiResponse(code = 500, message = "create vnfModule failed, examine entity object for details")})
288     public Response createVfModule(
289             @ApiParam(value = "aaiVnfId", required = true) @PathParam("aaiVnfId") String aaiVnfId,
290             @ApiParam(value = "mode", required = true) @QueryParam("mode") String mode,
291             @ApiParam(value = "CreateVfModuleRequest", required = true) final CreateVfModuleRequest req) {
292         logger.debug("Create VfModule enter inside VnfAdapterRest: " + req.toJsonString());
293         if (aaiVnfId == null || !aaiVnfId.equals(req.getVnfId())) {
294             logger.debug("Req rejected - aaiVnfId not provided or doesn't match URL");
295             return Response.status(HttpStatus.SC_BAD_REQUEST).type(MediaType.TEXT_PLAIN)
296                     .entity("vnfid in URL does not match content").build();
297         }
298
299         CreateVfModuleTask task = new CreateVfModuleTask(req, mode);
300         if (req.isSynchronous()) {
301             // This is a synchronous request
302             task.run();
303             return Response.status(task.getStatusCode()).entity(task.getGenericEntityResponse()).build();
304         } else {
305             // This is an asynchronous request
306             try {
307                 Thread t1 = new Thread(task);
308                 t1.start();
309             } catch (Exception e) {
310                 // problem handling create, send generic failure as sync resp to caller
311                 logger.error("{} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), "createVfModule",
312                         ErrorCode.BusinessProcesssError.getValue(), "Exception - createVfModule", e);
313                 return Response.serverError().build();
314             }
315             // send sync response (ACK) to caller
316             logger.debug("createVfModule exit");
317             return Response.status(HttpStatus.SC_ACCEPTED).build();
318         }
319     }
320
321     public class CreateVfModuleTask implements Runnable {
322         private final CreateVfModuleRequest req;
323         private CreateVfModuleResponse response = null;
324         private VfModuleExceptionResponse eresp = null;
325         private boolean sendxml;
326         private String mode;
327
328         public CreateVfModuleTask(CreateVfModuleRequest req, String mode) {
329             this.req = req;
330             this.sendxml = true; // can be set with a field or header later
331             this.mode = mode;
332         }
333
334         public int getStatusCode() {
335             return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
336         }
337
338         public Object getGenericEntityResponse() {
339             return (response != null) ? new GenericEntity<CreateVfModuleResponse>(response) {}
340                     : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
341         }
342
343         private String getResponse() {
344             if (response != null) {
345                 return sendxml ? response.toXmlString() : response.toJsonString();
346             } else {
347                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
348             }
349         }
350
351         @Override
352         public void run() {
353             logger.debug("CreateVfModuleTask start");
354             try {
355                 // Synchronous Web Service Outputs
356                 Holder<String> vfModuleStackId = new Holder<String>();
357                 Holder<Map<String, String>> outputs = new Holder<Map<String, String>>();
358                 Holder<VnfRollback> vnfRollback = new Holder<VnfRollback>();
359                 String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
360                 logger.debug("completeVnfVfModuleType=" + completeVnfVfModuleType);
361
362                 String cloudsiteId = req.getCloudSiteId();
363                 String cloudOwner = req.getCloudOwner();
364                 if (cloudsiteId != null && cloudsiteId.equals(TESTING_KEYWORD)) {
365                     String tenant = req.getTenantId();
366                     if (tenant != null && tenant.equals(TESTING_KEYWORD)) {
367                         throw new VnfException("testing.");
368                     }
369                     vnfRollback.value = new VnfRollback(req.getVnfId(), tenant, cloudOwner, cloudsiteId, true, false,
370                             new MsoRequest("reqid", "svcid"), req.getVolumeGroupId(), req.getVolumeGroupId(),
371                             req.getRequestType(), req.getModelCustomizationUuid());
372                     vfModuleStackId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
373                     outputs.value = VolumeAdapterRest.testMap();
374                 } else {
375                     // Support different Adapter Implementations
376                     MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsiteId);
377                     adapter.createVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
378                             completeVnfVfModuleType, req.getVnfVersion(), req.getVnfId(), req.getVfModuleName(),
379                             req.getVfModuleId(), req.getRequestType(), req.getVolumeGroupStackId(),
380                             req.getBaseVfModuleStackId(), req.getModelCustomizationUuid(), req.getVfModuleParams(),
381                             req.getFailIfExists(), req.getBackout(), req.getEnableBridge(), req.getMsoRequest(),
382                             vfModuleStackId, outputs, vnfRollback);
383                 }
384                 VfModuleRollback modRollback = new VfModuleRollback(vnfRollback.value, req.getVfModuleId(),
385                         vfModuleStackId.value, req.getMessageId());
386                 response = new CreateVfModuleResponse(req.getVnfId(), req.getVfModuleId(), vfModuleStackId.value,
387                         Boolean.TRUE, outputs.value, modRollback, req.getMessageId());
388             } catch (VnfException e) {
389                 eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE,
390                         req.getMessageId());
391             }
392             if (!req.isSynchronous()) {
393                 BpelRestClient bpelClient = bpelRestClientProvider.get();
394                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
395             }
396             logger.debug("CreateVfModuleTask exit: code=" + getStatusCode() + RESP + getResponse());
397         }
398     }
399
400     @PUT
401     @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}")
402     @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
403     @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
404     @ApiOperation(value = "UpdateVfModule", response = Response.class, notes = "Update an existing vnfModule")
405     @ApiResponses({@ApiResponse(code = 200, message = "vnfModule has been successfully updated"),
406             @ApiResponse(code = 202, message = "update vnfModule request has been successfully accepted (async only)"),
407             @ApiResponse(code = 500, message = "update vnfModule failed, examine entity object for details")})
408     public Response updateVfModule(
409             @ApiParam(value = "aaiVnfId", required = true) @PathParam("aaiVnfId") String aaiVnfId,
410             @ApiParam(value = "aaiVfModuleId", required = true) @PathParam("aaiVfModuleId") String aaiVfModuleId,
411             @ApiParam(value = "mode", required = true) @QueryParam("mode") String mode,
412             @ApiParam(value = "UpdateVfModuleRequest", required = true) final UpdateVfModuleRequest req) {
413         logger.debug("Update VfModule enter: " + req.toJsonString());
414         UpdateVfModulesTask task = new UpdateVfModulesTask(req, mode);
415         if (req.isSynchronous()) {
416             // This is a synchronous request
417             task.run();
418             return Response.status(task.getStatusCode()).entity(task.getGenericEntityResponse()).build();
419         } else {
420             // This is an asynchronous request
421             try {
422                 Thread t1 = new Thread(task);
423                 t1.start();
424             } catch (Exception e) {
425                 // problem handling create, send generic failure as sync resp to caller
426                 logger.error("{} {} {} {}", MessageEnum.RA_UPDATE_VNF_ERR.toString(), "updateVfModule",
427                         ErrorCode.BusinessProcesssError.getValue(), "Exception - updateVfModule", e);
428                 return Response.serverError().build();
429             }
430             // send sync response (ACK) to caller
431             logger.debug("updateVfModules exit");
432             return Response.status(HttpStatus.SC_ACCEPTED).build();
433         }
434     }
435
436     public class UpdateVfModulesTask implements Runnable {
437         private final UpdateVfModuleRequest req;
438         private UpdateVfModuleResponse response = null;
439         private VfModuleExceptionResponse eresp = null;
440         private boolean sendxml;
441         private String mode;
442
443         public UpdateVfModulesTask(UpdateVfModuleRequest req, String mode) {
444             this.req = req;
445             this.sendxml = true; // can be set with a field or header later
446             this.mode = mode;
447         }
448
449         public int getStatusCode() {
450             return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
451         }
452
453         public Object getGenericEntityResponse() {
454             return (response != null) ? new GenericEntity<UpdateVfModuleResponse>(response) {}
455                     : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
456         }
457
458         private String getResponse() {
459             if (response != null) {
460                 return sendxml ? response.toXmlString() : response.toJsonString();
461             } else {
462                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
463             }
464         }
465
466         @Override
467         public void run() {
468             try {
469                 // MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl (msoPropertiesFactory, cloudConfigFactory);
470
471                 // Synchronous Web Service Outputs
472                 Holder<String> vfModuleStackId = new Holder<String>();
473                 Holder<Map<String, String>> outputs = new Holder<Map<String, String>>();
474                 Holder<VnfRollback> vnfRollback = new Holder<VnfRollback>();
475                 String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
476                 logger.debug("in updateVf - completeVnfVfModuleType=" + completeVnfVfModuleType);
477
478                 String cloudsiteId = req.getCloudSiteId();
479
480                 // Support different Adapter Implementations
481                 MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsiteId);
482                 adapter.updateVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
483                         completeVnfVfModuleType, req.getVnfVersion(), req.getVfModuleName(), req.getRequestType(),
484                         req.getVolumeGroupStackId(), req.getBaseVfModuleId(), req.getVfModuleStackId(),
485                         req.getModelCustomizationUuid(), req.getVfModuleParams(), req.getMsoRequest(), outputs,
486                         vnfRollback);
487
488                 response = new UpdateVfModuleResponse(req.getVnfId(), req.getVfModuleId(), vfModuleStackId.value,
489                         outputs.value, req.getMessageId());
490             } catch (VnfException e) {
491                 eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.TRUE,
492                         req.getMessageId());
493             }
494             if (!req.isSynchronous()) {
495                 // This is asynch, so POST response back to caller
496                 BpelRestClient bpelClient = bpelRestClientProvider.get();
497                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
498             }
499             logger.debug("Update VfModule exit: code=" + getStatusCode() + RESP + getResponse());
500         }
501     }
502
503     /*
504      * URL:http://localhost:8080/vnfs/rest/v2/vnfs/<aaivnfid>/vf-modules/<aaimodid>/rollback REQUEST:
505      * {"deleteVfModuleRequest": {"cloudSiteId": "DAN", "tenantId": "214b428a1f554c02935e66330f6a5409", "vnfId":
506      * "somevnfid", "vfModuleId": "somemodid", "vfModuleStackId": "4e567676-e266-4594-a3a6-131c8a2baf73", "messageId":
507      * "ra.1", "notificationUrl": "http://localhost:8089/vnfmock", "skipAAI": true, "msoRequest": { "requestId": "ra1",
508      * "serviceInstanceId": "sa1" }} }
509      */
510     @DELETE
511     @Path("{aaiVnfId}/vf-modules/{aaiVfModuleId}/rollback")
512     @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
513     @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
514     @ApiOperation(value = "RollbackVfModule", response = Response.class, notes = "Rollback an existing vnfModule")
515     @ApiResponses({@ApiResponse(code = 200, message = "vnfModule has been successfully rolled back"),
516             @ApiResponse(code = 202,
517                     message = "rollback vnfModule request has been successfully accepted (async only)"),
518             @ApiResponse(code = 500, message = "rollback vnfModule failed, examine entity object for details")})
519     public Response rollbackVfModule(
520             @ApiParam(value = "aaiVnfId", required = true) @PathParam("aaiVnfId") String aaiVnfId,
521             @ApiParam(value = "aaiVfModuleId", required = true) @PathParam("aaiVfModuleId") String aaiVfModuleId,
522             @ApiParam(value = "RollbackVfModuleRequest", required = true)
523             // @QueryParam("rollback") String rollback,
524             final RollbackVfModuleRequest req) {
525         logger.debug("Rollback VfModule enter: " + req.toJsonString());
526         RollbackVfModulesTask task = new RollbackVfModulesTask(req);
527         if (req.isSynchronous()) {
528             // This is a synchronous request
529             task.run();
530             return Response.status(task.getStatusCode()).entity(task.getGenericEntityResponse()).build();
531         } else {
532             // This is an asynchronous request
533             try {
534                 Thread t1 = new Thread(task);
535                 t1.start();
536             } catch (Exception e) {
537                 // problem handling create, send generic failure as sync resp to caller
538                 logger.error("{} {} {} {}", MessageEnum.RA_ROLLBACK_VNF_ERR.toString(), "rollbackVfModule",
539                         ErrorCode.BusinessProcesssError.getValue(), "Exception - rollbackVfModule", e);
540                 return Response.serverError().build();
541             }
542             // send sync response (ACK) to caller
543             logger.debug("rollbackVfModule exit");
544             return Response.status(HttpStatus.SC_ACCEPTED).build();
545         }
546     }
547
548     public class RollbackVfModulesTask implements Runnable {
549         private final RollbackVfModuleRequest req;
550         private RollbackVfModuleResponse response = null;
551         private VfModuleExceptionResponse eresp = null;
552         private boolean sendxml;
553
554         public RollbackVfModulesTask(RollbackVfModuleRequest req) {
555             this.req = req;
556             this.sendxml = true; // can be set with a field or header later
557         }
558
559         public int getStatusCode() {
560             return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
561         }
562
563         public Object getGenericEntityResponse() {
564             return (response != null) ? new GenericEntity<RollbackVfModuleResponse>(response) {}
565                     : new GenericEntity<VfModuleExceptionResponse>(eresp) {};
566         }
567
568         private String getResponse() {
569             if (response != null) {
570                 return sendxml ? response.toXmlString() : response.toJsonString();
571             } else {
572                 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
573             }
574         }
575
576         @Override
577         public void run() {
578             try {
579                 VfModuleRollback vmr = req.getVfModuleRollback();
580                 VnfRollback vrb = new VnfRollback(vmr.getVfModuleStackId(), vmr.getTenantId(), vmr.getCloudOwner(),
581                         vmr.getCloudSiteId(), true, vmr.isVfModuleCreated(), vmr.getMsoRequest(), null, null, null,
582                         null);
583
584                 // Support multiple adapter implementations
585                 MsoVnfAdapter adapter = vnfAdapterRestUtils.getVnfAdapterImpl(vmr.getMode(), vmr.getCloudSiteId());
586                 adapter.rollbackVnf(vrb);
587
588                 response = new RollbackVfModuleResponse(Boolean.TRUE, req.getMessageId());
589             } catch (VnfException e) {
590                 logger.error("{} {} {}", MessageEnum.RA_ROLLBACK_VNF_ERR.toString(),
591                         ErrorCode.BusinessProcesssError.getValue(), "Exception - rollbackVfModule", e);
592                 eresp = new VfModuleExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, false,
593                         req.getMessageId());
594             }
595             if (!req.isSynchronous()) {
596                 // This is asynch, so POST response back to caller
597                 BpelRestClient bpelClient = bpelRestClientProvider.get();
598                 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
599             }
600             logger.debug("RollbackVfModulesTask exit: code=" + getStatusCode() + RESP + getResponse());
601         }
602     }
603 }