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