2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.mso.adapters.vnf;
24 import java.util.HashMap;
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;
41 import org.apache.http.HttpStatus;
43 import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
44 import org.openecomp.mso.adapters.vnfrest.CreateVolumeGroupRequest;
45 import org.openecomp.mso.adapters.vnfrest.CreateVolumeGroupResponse;
46 import org.openecomp.mso.adapters.vnfrest.DeleteVolumeGroupRequest;
47 import org.openecomp.mso.adapters.vnfrest.DeleteVolumeGroupResponse;
48 import org.openecomp.mso.adapters.vnfrest.QueryVolumeGroupResponse;
49 import org.openecomp.mso.adapters.vnfrest.RollbackVolumeGroupRequest;
50 import org.openecomp.mso.adapters.vnfrest.RollbackVolumeGroupResponse;
51 import org.openecomp.mso.adapters.vnfrest.UpdateVolumeGroupRequest;
52 import org.openecomp.mso.adapters.vnfrest.UpdateVolumeGroupResponse;
53 import org.openecomp.mso.adapters.vnfrest.VolumeGroupExceptionResponse;
54 import org.openecomp.mso.adapters.vnfrest.VolumeGroupRollback;
55 import org.openecomp.mso.entity.MsoRequest;
56 import org.openecomp.mso.logger.MessageEnum;
57 import org.openecomp.mso.logger.MsoLogger;
58 import org.openecomp.mso.openstack.beans.VnfRollback;
59 import org.openecomp.mso.openstack.beans.VnfStatus;
60 import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
63 * This class services calls to the REST interface for VNF Volumes (http://host:port/vnfs/rest/v1/volume-groups)
64 * Both XML and JSON can be produced/consumed. Set Accept: and Content-Type: headers appropriately. XML is the default.
65 * For testing, call with cloudSiteId = ___TESTING___
66 * To test exceptions, also set tenantId = ___TESTING___
68 * V2 incorporates run-time selection of sub-orchestrator implementation (Heat or Cloudify)
69 * based on the target cloud.
71 @Path("/v2/volume-groups")
72 public class VolumeAdapterRestV2 {
73 private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA);
74 private static final String TESTING_KEYWORD = "___TESTING___";
78 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
79 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
80 public Response createVNFVolumes(
81 @QueryParam("mode") String mode,
82 final CreateVolumeGroupRequest req)
84 LOGGER.debug("createVNFVolumes enter: " + req.toJsonString());
85 CreateVNFVolumesTask task = new CreateVNFVolumesTask(req, mode);
86 if (req.isSynchronous()) {
87 // This is a synchronous request
90 .status(task.getStatusCode())
91 .entity(task.getGenericEntityResponse())
94 // This is an asynchronous request
96 Thread t1 = new Thread(task);
98 } catch (Exception e) {
99 // problem handling create, send generic failure as sync resp to caller
100 LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, "", "createVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - createVNFVolumes", e);
101 return Response.serverError().build();
103 // send sync response (ACK) to caller
104 LOGGER.debug ("createVNFVolumes exit");
105 return Response.status(HttpStatus.SC_ACCEPTED).build();
109 public class CreateVNFVolumesTask implements Runnable {
110 private final CreateVolumeGroupRequest req;
111 private CreateVolumeGroupResponse response = null;
112 private VolumeGroupExceptionResponse eresp = null;
113 private boolean sendxml;
116 public CreateVNFVolumesTask(CreateVolumeGroupRequest req, String mode) {
118 this.sendxml = true; // can be set with a field or header later
121 public int getStatusCode() {
122 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
124 public Object getGenericEntityResponse() {
125 return (response != null)
126 ? new GenericEntity<CreateVolumeGroupResponse>(response) {}
127 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
129 private String getResponse() {
130 if (response != null) {
131 return sendxml ? response.toXmlString() : response.toJsonString();
133 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
138 LOGGER.debug ("CreateVFModule VolumesTask start");
140 // Synchronous Web Service Outputs
141 Holder<String> stackId = new Holder<>();
142 Holder<Map<String, String>> outputs = new Holder<>();
143 Holder<VnfRollback> vnfRollback = new Holder<>();
144 String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
145 LOGGER.debug("in createVfModuleVolumes - completeVnfVfModuleType=" + completeVnfVfModuleType);
147 String cloudsiteId = req.getCloudSiteId();
148 if (cloudsiteId != null && cloudsiteId.equals(TESTING_KEYWORD)) {
149 String tenant = req.getTenantId();
150 if (tenant != null && tenant.equals(TESTING_KEYWORD)) {
151 throw new VnfException("testing.");
153 stackId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
154 outputs.value = testMap();
156 // Support different Adapter Implementations
157 MsoVnfAdapter vnfAdapter = VnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudsiteId);
158 vnfAdapter.createVfModule(
159 req.getCloudSiteId(), //cloudSiteId,
160 req.getTenantId(), //tenantId,
161 completeVnfVfModuleType, //vnfType,
162 req.getVnfVersion(), //vnfVersion,
163 req.getVolumeGroupName(), //vnfName,
164 "VOLUME", //requestType,
165 null, //volumeGroupHeatStackId,
166 null, //baseVfHeatStackId,
167 req.getModelCustomizationUuid(),
168 req.getVolumeGroupParams(), //inputs,
169 req.getFailIfExists(), //failIfExists,
170 req.getSuppressBackout(), //backout,
171 req.getMsoRequest(), // msoRequest,
177 VolumeGroupRollback rb = new VolumeGroupRollback(
178 req.getVolumeGroupId(),
180 vnfRollback.value.getVnfCreated(),
182 req.getCloudSiteId(),
186 response = new CreateVolumeGroupResponse(
187 req.getVolumeGroupId(),
189 vnfRollback.value.getVnfCreated(),
193 } catch (VnfException e) {
194 LOGGER.debug("Exception :",e);
195 eresp = new VolumeGroupExceptionResponse(
196 e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
198 if (!req.isSynchronous()) {
199 // This is asynch, so POST response back to caller
200 BpelRestClient bpelClient = new BpelRestClient();
201 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
203 LOGGER.debug ("CreateVFModule VolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
208 @Path("{aaiVolumeGroupId}")
209 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
210 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
211 public Response deleteVNFVolumes(
212 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
213 @QueryParam("mode") String mode,
214 final DeleteVolumeGroupRequest req
217 LOGGER.debug("deleteVNFVolumes enter: " + req.toJsonString());
218 if (aaiVolumeGroupId == null || !aaiVolumeGroupId.equals(req.getVolumeGroupId())) {
220 .status(HttpStatus.SC_BAD_REQUEST)
221 .type(MediaType.TEXT_PLAIN)
222 .entity("VolumeGroupId in URL does not match content")
225 DeleteVNFVolumesTask task = new DeleteVNFVolumesTask(req, mode);
226 if (req.isSynchronous()) {
227 // This is a synchronous request
230 .status(task.getStatusCode())
231 .entity(task.getGenericEntityResponse())
234 // This is an asynchronous request
236 Thread t1 = new Thread(task);
238 } catch (Exception e) {
239 // problem handling create, send generic failure as sync resp to caller
240 LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, "", "deleteVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - deleteVNFVolumes", e);
241 return Response.serverError().build();
243 // send sync response (ACK) to caller
244 LOGGER.debug ("deleteVNFVolumes exit");
245 return Response.status(HttpStatus.SC_ACCEPTED).build();
249 public class DeleteVNFVolumesTask implements Runnable {
250 private final DeleteVolumeGroupRequest req;
251 private DeleteVolumeGroupResponse response = null;
252 private VolumeGroupExceptionResponse eresp = null;
253 private boolean sendxml;
256 public DeleteVNFVolumesTask(DeleteVolumeGroupRequest req, String mode) {
258 this.sendxml = true; // can be set with a field or header later
261 public int getStatusCode() {
262 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
264 public Object getGenericEntityResponse() {
265 return (response != null)
266 ? new GenericEntity<DeleteVolumeGroupResponse>(response) {}
267 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
269 private String getResponse() {
270 if (response != null) {
271 return sendxml ? response.toXmlString() : response.toJsonString();
273 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
278 LOGGER.debug("DeleteVNFVolumesTask start");
279 String cloudSiteId = req.getCloudSiteId();
281 if (! cloudSiteId.equals(TESTING_KEYWORD)) {
282 // Support different Adapter Implementations
283 MsoVnfAdapter vnfAdapter = VnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudSiteId);
284 vnfAdapter.deleteVnf(req.getCloudSiteId(), req.getTenantId(), req.getVolumeGroupStackId(), req.getMsoRequest());
286 response = new DeleteVolumeGroupResponse(true, req.getMessageId());
287 } catch (VnfException e) {
288 LOGGER.debug("Exception :",e);
289 eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
291 if (!req.isSynchronous()) {
292 // This is asynch, so POST response back to caller
293 BpelRestClient bpelClient = new BpelRestClient();
294 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
296 LOGGER.debug("DeleteVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
301 @Path("{aaiVolumeGroupId}/rollback")
302 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
303 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
304 public Response rollbackVNFVolumes(
305 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
306 final RollbackVolumeGroupRequest req
309 LOGGER.debug("rollbackVNFVolumes enter: " + req.toJsonString());
310 if (aaiVolumeGroupId == null || req.getVolumeGroupRollback() == null || !aaiVolumeGroupId.equals(req.getVolumeGroupRollback().getVolumeGroupId())) {
312 .status(HttpStatus.SC_BAD_REQUEST)
313 .type(MediaType.TEXT_PLAIN)
314 .entity("VolumeGroupId in URL does not match content")
317 RollbackVNFVolumesTask task = new RollbackVNFVolumesTask(req);
318 if (req.isSynchronous()) {
319 // This is a synchronous request
322 .status(task.getStatusCode())
323 .entity(task.getGenericEntityResponse())
326 // This is an asynchronous request
328 Thread t1 = new Thread(task);
330 } catch (Exception e) {
331 // problem handling create, send generic failure as sync resp to caller
332 LOGGER.error (MessageEnum.RA_ROLLBACK_VNF_ERR, "", "rollbackVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - rollbackVNFVolumes", e);
333 return Response.serverError().build();
335 // send sync response (ACK) to caller
336 LOGGER.debug("rollbackVNFVolumes exit");
337 return Response.status(HttpStatus.SC_ACCEPTED).build();
341 public class RollbackVNFVolumesTask implements Runnable {
342 private final RollbackVolumeGroupRequest req;
343 private RollbackVolumeGroupResponse response = null;
344 private VolumeGroupExceptionResponse eresp = null;
345 private boolean sendxml;
347 public RollbackVNFVolumesTask(RollbackVolumeGroupRequest req) {
349 this.sendxml = true; // can be set with a field or header later
351 public int getStatusCode() {
352 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
354 public Object getGenericEntityResponse() {
355 return (response != null)
356 ? new GenericEntity<RollbackVolumeGroupResponse>(response) {}
357 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
359 private String getResponse() {
360 if (response != null) {
361 return sendxml ? response.toXmlString() : response.toJsonString();
363 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
368 LOGGER.debug("RollbackVNFVolumesTask start");
370 VolumeGroupRollback vgr = req.getVolumeGroupRollback();
371 VnfRollback vrb = new VnfRollback(
372 vgr.getVolumeGroupStackId(), vgr.getTenantId(), vgr.getCloudSiteId(), true, true,
373 vgr.getMsoRequest(), null, null, null, null);
375 // Support different Adapter Implementations
376 MsoVnfAdapter vnfAdapter = VnfAdapterRestUtils.getVnfAdapterImpl(vrb.getMode(), vrb.getCloudSiteId());
377 vnfAdapter.rollbackVnf(vrb);
378 response = new RollbackVolumeGroupResponse(true, req.getMessageId());
379 } catch (VnfException e) {
380 LOGGER.debug("Exception :",e);
381 eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
383 if (!req.isSynchronous()) {
384 // This is asynch, so POST response back to caller
385 BpelRestClient bpelClient = new BpelRestClient();
386 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
388 LOGGER.debug("RollbackVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
394 @Path("{aaiVolumeGroupId}")
395 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
396 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
397 public Response updateVNFVolumes(
398 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
399 @QueryParam("mode") String mode,
400 final UpdateVolumeGroupRequest req
403 LOGGER.debug("updateVNFVolumes enter: " + req.toJsonString());
404 if (aaiVolumeGroupId == null || !aaiVolumeGroupId.equals(req.getVolumeGroupId())) {
406 .status(HttpStatus.SC_BAD_REQUEST)
407 .type(MediaType.TEXT_PLAIN)
408 .entity("VolumeGroupId in URL does not match content")
411 UpdateVNFVolumesTask task = new UpdateVNFVolumesTask(req, mode);
412 if (req.isSynchronous()) {
413 // This is a synchronous request
416 .status(task.getStatusCode())
417 .entity(task.getGenericEntityResponse())
420 // This is an asynchronous request
422 Thread t1 = new Thread(task);
424 } catch (Exception e) {
425 // problem handling create, send generic failure as sync resp to caller
426 LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, "", "updateVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - updateVNFVolumes", e);
427 return Response.serverError().build();
429 // send sync response (ACK) to caller
430 LOGGER.debug ("updateVNFVolumes exit");
431 return Response.status(HttpStatus.SC_ACCEPTED).build();
435 public class UpdateVNFVolumesTask implements Runnable {
436 private final UpdateVolumeGroupRequest req;
437 private UpdateVolumeGroupResponse response = null;
438 private VolumeGroupExceptionResponse eresp = null;
439 private boolean sendxml;
442 public UpdateVNFVolumesTask(UpdateVolumeGroupRequest req, String mode) {
444 this.sendxml = true; // can be set with a field or header later
447 public int getStatusCode() {
448 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
450 public Object getGenericEntityResponse() {
451 return (response != null)
452 ? new GenericEntity<UpdateVolumeGroupResponse>(response) {}
453 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
455 private String getResponse() {
456 if (response != null) {
457 return sendxml ? response.toXmlString() : response.toJsonString();
459 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
464 LOGGER.debug("UpdateVNFVolumesTask start");
466 @SuppressWarnings("unused")
467 Holder<Map<String, String>> outputs = new Holder<> ();
468 Holder<VnfRollback> vnfRollback = new Holder<> ();
469 String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
470 LOGGER.debug("in updateVfModuleVolume - completeVnfVfModuleType=" + completeVnfVfModuleType);
472 if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
473 outputs.value = testMap();
475 // Support different Adapter Implementations
476 MsoVnfAdapter vnfAdapter = VnfAdapterRestUtils.getVnfAdapterImpl(mode, req.getCloudSiteId());
477 vnfAdapter.updateVfModule (req.getCloudSiteId(),
480 completeVnfVfModuleType,
482 req.getVolumeGroupStackId(),
486 req.getVolumeGroupStackId(),
487 req.getModelCustomizationUuid(),
488 req.getVolumeGroupParams(),
493 response = new UpdateVolumeGroupResponse(
494 req.getVolumeGroupId(), req.getVolumeGroupStackId(),
495 outputs.value, req.getMessageId());
496 } catch (VnfException e) {
497 LOGGER.debug("Exception :",e);
498 eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
500 if (!req.isSynchronous()) {
501 // This is asynch, so POST response back to caller
502 BpelRestClient bpelClient = new BpelRestClient();
503 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
505 LOGGER.debug("UpdateVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
510 @Path("{aaiVolumeGroupId}")
511 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
512 public Response queryVNFVolumes(
513 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
514 @QueryParam("cloudSiteId") String cloudSiteId,
515 @QueryParam("tenantId") String tenantId,
516 @QueryParam("volumeGroupStackId") String volumeGroupStackId,
517 @QueryParam("skipAAI") Boolean skipAAI,
518 @QueryParam("msoRequest.requestId") String requestId,
519 @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId,
520 @QueryParam("mode") String mode
523 //This request responds synchronously only
524 LOGGER.debug ("queryVNFVolumes enter:" + aaiVolumeGroupId + " " + volumeGroupStackId);
525 MsoRequest msoRequest = new MsoRequest(requestId, serviceInstanceId);
528 int respStatus = HttpStatus.SC_OK;
529 QueryVolumeGroupResponse qryResp = new QueryVolumeGroupResponse(aaiVolumeGroupId, volumeGroupStackId, null, null);
530 Holder<Boolean> vnfExists = new Holder<>();
531 Holder<String> vfModuleId = new Holder<>();
532 Holder<VnfStatus> status = new Holder<>();
533 Holder<Map<String, String>> outputs = new Holder<>();
534 if (cloudSiteId != null && cloudSiteId.equals(TESTING_KEYWORD)) {
535 if (tenantId != null && tenantId.equals(TESTING_KEYWORD)) {
536 throw new VnfException("testing.");
538 vnfExists.value = true;
539 vfModuleId.value = TESTING_KEYWORD;
540 status.value = VnfStatus.ACTIVE;
541 outputs.value = testMap();
543 // Support different Adapter Implementations
544 MsoVnfAdapter vnfAdapter = VnfAdapterRestUtils.getVnfAdapterImpl(mode, cloudSiteId);
545 vnfAdapter.queryVnf(cloudSiteId, tenantId, volumeGroupStackId, msoRequest, vnfExists, vfModuleId, status, outputs);
547 if (!vnfExists.value) {
548 LOGGER.debug ("VNFVolumes not found");
549 qryResp.setVolumeGroupStatus(status.value);
550 respStatus = HttpStatus.SC_NOT_FOUND;
552 LOGGER.debug ("VNFVolumes found " + vfModuleId.value + ", status=" + status.value);
553 qryResp.setVolumeGroupStatus(status.value);
554 qryResp.setVolumeGroupOutputs(outputs.value);
556 LOGGER.debug("Query queryVNFVolumes exit");
559 .entity(new GenericEntity<QueryVolumeGroupResponse>(qryResp) {})
561 } catch (VnfException e) {
562 LOGGER.error(MessageEnum.RA_QUERY_VNF_ERR, aaiVolumeGroupId, "", "queryVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "VnfException - queryVNFVolumes", e);
563 VolumeGroupExceptionResponse excResp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.FALSE, null);
564 LOGGER.debug("Query queryVNFVolumes exit");
566 .status(HttpStatus.SC_INTERNAL_SERVER_ERROR)
567 .entity(new GenericEntity<VolumeGroupExceptionResponse>(excResp) {})
571 public static Map<String, String> testMap() {
572 Map<String, String> m = new HashMap<>();
573 m.put("mickey", "7");
574 m.put("clyde", "10");
575 m.put("wayne", "99");