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