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