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