2 * ============LICENSE_START=======================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.openecomp.mso.adapters.vnf;
25 import java.util.HashMap;
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;
42 import org.apache.http.HttpStatus;
44 import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
45 import org.openecomp.mso.adapters.vnfrest.CreateVolumeGroupRequest;
46 import org.openecomp.mso.adapters.vnfrest.CreateVolumeGroupResponse;
47 import org.openecomp.mso.adapters.vnfrest.DeleteVolumeGroupRequest;
48 import org.openecomp.mso.adapters.vnfrest.DeleteVolumeGroupResponse;
49 import org.openecomp.mso.adapters.vnfrest.QueryVolumeGroupResponse;
50 import org.openecomp.mso.adapters.vnfrest.RollbackVolumeGroupRequest;
51 import org.openecomp.mso.adapters.vnfrest.RollbackVolumeGroupResponse;
52 import org.openecomp.mso.adapters.vnfrest.UpdateVolumeGroupRequest;
53 import org.openecomp.mso.adapters.vnfrest.UpdateVolumeGroupResponse;
54 import org.openecomp.mso.adapters.vnfrest.VolumeGroupExceptionResponse;
55 import org.openecomp.mso.adapters.vnfrest.VolumeGroupRollback;
56 import org.openecomp.mso.cloud.CloudConfigFactory;
57 import org.openecomp.mso.entity.MsoRequest;
58 import org.openecomp.mso.logger.MessageEnum;
59 import org.openecomp.mso.logger.MsoLogger;
60 import org.openecomp.mso.openstack.beans.VnfRollback;
61 import org.openecomp.mso.openstack.beans.VnfStatus;
62 import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
63 import org.openecomp.mso.properties.MsoPropertiesFactory;
66 * This class services calls to the REST interface for VNF Volumes (http://host:port/vnfs/rest/v1/volume-groups)
67 * Both XML and JSON can be produced/consumed. Set Accept: and Content-Type: headers appropriately. XML is the default.
68 * For testing, call with cloudSiteId = ___TESTING___
69 * To test exceptions, also set tenantId = ___TESTING___
71 @Path("/v1/volume-groups")
72 public class VolumeAdapterRest {
73 private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA);
74 private static final String TESTING_KEYWORD = "___TESTING___";
75 private final CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
76 private final MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
77 private final MsoVnfAdapter vnfAdapter = new MsoVnfAdapterImpl(msoPropertiesFactory, cloudConfigFactory);
81 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
82 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
83 public Response createVNFVolumes(final CreateVolumeGroupRequest req) {
84 LOGGER.debug("createVNFVolumes enter: " + req.toJsonString());
85 CreateVNFVolumesTask task = new CreateVNFVolumesTask(req);
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;
115 public CreateVNFVolumesTask(CreateVolumeGroupRequest req) {
117 this.sendxml = true; // can be set with a field or header later
119 public int getStatusCode() {
120 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
122 public Object getGenericEntityResponse() {
123 return (response != null)
124 ? new GenericEntity<CreateVolumeGroupResponse>(response) {}
125 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
127 private String getResponse() {
128 if (response != null) {
129 return sendxml ? response.toXmlString() : response.toJsonString();
131 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
136 LOGGER.debug ("CreateVFModule VolumesTask start");
138 // Synchronous Web Service Outputs
139 Holder<String> stackId = new Holder<>();
140 Holder<Map<String, String>> outputs = new Holder<>();
141 Holder<VnfRollback> vnfRollback = new Holder<>();
142 String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
143 LOGGER.debug("in createVfModuleVolumes - completeVnfVfModuleType=" + completeVnfVfModuleType);
145 String cloudsite = req.getCloudSiteId();
146 if (cloudsite != null && cloudsite.equals(TESTING_KEYWORD)) {
147 String tenant = req.getTenantId();
148 if (tenant != null && tenant.equals(TESTING_KEYWORD)) {
149 throw new VnfException("testing.");
151 stackId.value = "479D3D8B-6360-47BC-AB75-21CC91981484";
152 outputs.value = testMap();
154 // vnfAdapter.createVnf(
155 // req.getCloudSiteId(),
156 // req.getTenantId(),
158 // req.getVnfVersion(),
159 // req.getVolumeGroupName(),
160 // "VOLUME", // request type is VOLUME
161 // null, // not sure about this
162 // req.getVolumeGroupParams(),
163 // req.getFailIfExists(),
164 // req.getSuppressBackout(),
165 // req.getMsoRequest(),
169 vnfAdapter.createVfModule(
170 req.getCloudSiteId(), //cloudSiteId,
171 req.getTenantId(), //tenantId,
172 //req.getVnfType(), //vnfType,
173 completeVnfVfModuleType,
174 req.getVnfVersion(), //vnfVersion,
175 req.getVolumeGroupName(), //vnfName,
176 "VOLUME", //requestType,
177 null, //volumeGroupHeatStackId,
178 null, //baseVfHeatStackId,
179 req.getModelCustomizationUuid(),
180 req.getVolumeGroupParams(), //inputs,
181 req.getFailIfExists(), //failIfExists,
182 req.getSuppressBackout(), //backout,
183 req.getMsoRequest(), // msoRequest,
188 VolumeGroupRollback rb = new VolumeGroupRollback(
189 req.getVolumeGroupId(),
191 true, // TODO boolean volumeGroupCreated, when would it be false?
193 req.getCloudSiteId(),
196 response = new CreateVolumeGroupResponse(
197 req.getVolumeGroupId(),
199 true, // TODO boolean volumeGroupCreated, when would it be false?
203 } catch (VnfException e) {
204 LOGGER.debug("Exception :",e);
205 eresp = new VolumeGroupExceptionResponse(
206 e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
208 if (!req.isSynchronous()) {
209 // This is asynch, so POST response back to caller
210 BpelRestClient bpelClient = new BpelRestClient();
211 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
213 LOGGER.debug ("CreateVFModule VolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
218 @Path("{aaiVolumeGroupId}")
219 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
220 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
221 public Response deleteVNFVolumes(
222 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
223 final DeleteVolumeGroupRequest req
226 LOGGER.debug("deleteVNFVolumes enter: " + req.toJsonString());
227 if (aaiVolumeGroupId == null || !aaiVolumeGroupId.equals(req.getVolumeGroupId())) {
229 .status(HttpStatus.SC_BAD_REQUEST)
230 .type(MediaType.TEXT_PLAIN)
231 .entity("VolumeGroupId in URL does not match content")
234 DeleteVNFVolumesTask task = new DeleteVNFVolumesTask(req);
235 if (req.isSynchronous()) {
236 // This is a synchronous request
239 .status(task.getStatusCode())
240 .entity(task.getGenericEntityResponse())
243 // This is an asynchronous request
245 Thread t1 = new Thread(task);
247 } catch (Exception e) {
248 // problem handling create, send generic failure as sync resp to caller
249 LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, "", "deleteVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - deleteVNFVolumes", e);
250 return Response.serverError().build();
252 // send sync response (ACK) to caller
253 LOGGER.debug ("deleteVNFVolumes exit");
254 return Response.status(HttpStatus.SC_ACCEPTED).build();
258 public class DeleteVNFVolumesTask implements Runnable {
259 private final DeleteVolumeGroupRequest req;
260 private DeleteVolumeGroupResponse response = null;
261 private VolumeGroupExceptionResponse eresp = null;
262 private boolean sendxml;
264 public DeleteVNFVolumesTask(DeleteVolumeGroupRequest req) {
266 this.sendxml = true; // can be set with a field or header later
268 public int getStatusCode() {
269 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
271 public Object getGenericEntityResponse() {
272 return (response != null)
273 ? new GenericEntity<DeleteVolumeGroupResponse>(response) {}
274 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
276 private String getResponse() {
277 if (response != null) {
278 return sendxml ? response.toXmlString() : response.toJsonString();
280 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
285 LOGGER.debug("DeleteVNFVolumesTask start");
287 if (!req.getCloudSiteId().equals(TESTING_KEYWORD)) {
288 vnfAdapter.deleteVnf(req.getCloudSiteId(), req.getTenantId(), req.getVolumeGroupStackId(), req.getMsoRequest());
290 response = new DeleteVolumeGroupResponse(true, req.getMessageId());
291 } catch (VnfException e) {
292 LOGGER.debug("Exception :",e);
293 eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
295 if (!req.isSynchronous()) {
296 // This is asynch, so POST response back to caller
297 BpelRestClient bpelClient = new BpelRestClient();
298 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
300 LOGGER.debug("DeleteVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
305 @Path("{aaiVolumeGroupId}/rollback")
306 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
307 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
308 public Response rollbackVNFVolumes(
309 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
310 final RollbackVolumeGroupRequest req
313 LOGGER.debug("rollbackVNFVolumes enter: " + req.toJsonString());
314 if (aaiVolumeGroupId == null || req.getVolumeGroupRollback() == null || !aaiVolumeGroupId.equals(req.getVolumeGroupRollback().getVolumeGroupId())) {
316 .status(HttpStatus.SC_BAD_REQUEST)
317 .type(MediaType.TEXT_PLAIN)
318 .entity("VolumeGroupId in URL does not match content")
321 RollbackVNFVolumesTask task = new RollbackVNFVolumesTask(req);
322 if (req.isSynchronous()) {
323 // This is a synchronous request
326 .status(task.getStatusCode())
327 .entity(task.getGenericEntityResponse())
330 // This is an asynchronous request
332 Thread t1 = new Thread(task);
334 } catch (Exception e) {
335 // problem handling create, send generic failure as sync resp to caller
336 LOGGER.error (MessageEnum.RA_ROLLBACK_VNF_ERR, "", "rollbackVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - rollbackVNFVolumes", e);
337 return Response.serverError().build();
339 // send sync response (ACK) to caller
340 LOGGER.debug("rollbackVNFVolumes exit");
341 return Response.status(HttpStatus.SC_ACCEPTED).build();
345 public class RollbackVNFVolumesTask implements Runnable {
346 private final RollbackVolumeGroupRequest req;
347 private RollbackVolumeGroupResponse response = null;
348 private VolumeGroupExceptionResponse eresp = null;
349 private boolean sendxml;
351 public RollbackVNFVolumesTask(RollbackVolumeGroupRequest req) {
353 this.sendxml = true; // can be set with a field or header later
355 public int getStatusCode() {
356 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
358 public Object getGenericEntityResponse() {
359 return (response != null)
360 ? new GenericEntity<RollbackVolumeGroupResponse>(response) {}
361 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
363 private String getResponse() {
364 if (response != null) {
365 return sendxml ? response.toXmlString() : response.toJsonString();
367 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
372 LOGGER.debug("DeleteVNFVolumesTask start");
374 VolumeGroupRollback vgr = req.getVolumeGroupRollback();
375 VnfRollback vrb = new VnfRollback(
376 vgr.getVolumeGroupStackId(), vgr.getTenantId(), vgr.getCloudSiteId(), true, true,
377 vgr.getMsoRequest(), null, null, null, null);
378 vnfAdapter.rollbackVnf(vrb);
379 response = new RollbackVolumeGroupResponse(true, req.getMessageId());
380 } catch (VnfException e) {
381 LOGGER.debug("Exception :",e);
382 eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
384 if (!req.isSynchronous()) {
385 // This is asynch, so POST response back to caller
386 BpelRestClient bpelClient = new BpelRestClient();
387 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
389 LOGGER.debug("DeleteVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
395 @Path("{aaiVolumeGroupId}")
396 @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
397 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
398 public Response updateVNFVolumes(
399 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
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);
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;
441 public UpdateVNFVolumesTask(UpdateVolumeGroupRequest req) {
443 this.sendxml = true; // can be set with a field or header later
445 public int getStatusCode() {
446 return (response != null) ? HttpStatus.SC_OK : HttpStatus.SC_BAD_REQUEST;
448 public Object getGenericEntityResponse() {
449 return (response != null)
450 ? new GenericEntity<UpdateVolumeGroupResponse>(response) {}
451 : new GenericEntity<VolumeGroupExceptionResponse>(eresp) {};
453 private String getResponse() {
454 if (response != null) {
455 return sendxml ? response.toXmlString() : response.toJsonString();
457 return sendxml ? eresp.toXmlString() : eresp.toJsonString();
462 LOGGER.debug("UpdateVNFVolumesTask start");
464 @SuppressWarnings("unused")
465 Holder<Map<String, String>> outputs = new Holder<> ();
466 Holder<VnfRollback> vnfRollback = new Holder<> ();
467 String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
468 LOGGER.debug("in updateVfModuleVolume - completeVnfVfModuleType=" + completeVnfVfModuleType);
470 if (req.getCloudSiteId().equals(TESTING_KEYWORD)) {
471 outputs.value = testMap();
473 //vnfAdapter.updateVnf(
474 // req.getCloudSiteId(),
475 // req.getTenantId(),
477 // req.getVnfVersion(),
478 // req.getVfModuleType(),
479 // "VOLUME", // request type is VOLUME
480 // req.getVolumeGroupStackId(),
481 // req.getVolumeGroupParams(),
482 // req.getMsoRequest(),
485 vnfAdapter.updateVfModule (req.getCloudSiteId(),
488 completeVnfVfModuleType,
490 req.getVolumeGroupStackId(),
494 req.getVolumeGroupStackId(),
495 req.getModelCustomizationUuid(),
496 req.getVolumeGroupParams(),
501 response = new UpdateVolumeGroupResponse(
502 req.getVolumeGroupId(), req.getVolumeGroupStackId(),
503 outputs.value, req.getMessageId());
504 } catch (VnfException e) {
505 LOGGER.debug("Exception :",e);
506 eresp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, true, req.getMessageId());
508 if (!req.isSynchronous()) {
509 // This is asynch, so POST response back to caller
510 BpelRestClient bpelClient = new BpelRestClient();
511 bpelClient.bpelPost(getResponse(), req.getNotificationUrl(), sendxml);
513 LOGGER.debug("UpdateVNFVolumesTask exit: code=" + getStatusCode() + ", resp="+ getResponse());
518 @Path("{aaiVolumeGroupId}")
519 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
520 public Response queryVNFVolumes(
521 @PathParam("aaiVolumeGroupId") String aaiVolumeGroupId,
522 @QueryParam("cloudSiteId") String cloudSiteId,
523 @QueryParam("tenantId") String tenantId,
524 @QueryParam("volumeGroupStackId") String volumeGroupStackId,
525 @QueryParam("skipAAI") Boolean skipAAI,
526 @QueryParam("msoRequest.requestId") String requestId,
527 @QueryParam("msoRequest.serviceInstanceId") String serviceInstanceId
530 //This request responds synchronously only
531 LOGGER.debug ("queryVNFVolumes enter:" + aaiVolumeGroupId + " " + volumeGroupStackId);
532 MsoRequest msoRequest = new MsoRequest(requestId, serviceInstanceId);
535 int respStatus = HttpStatus.SC_OK;
536 QueryVolumeGroupResponse qryResp = new QueryVolumeGroupResponse(aaiVolumeGroupId, volumeGroupStackId, null, null);
537 Holder<Boolean> vnfExists = new Holder<>();
538 Holder<String> vfModuleId = new Holder<>();
539 Holder<VnfStatus> status = new Holder<>();
540 Holder<Map<String, String>> outputs = new Holder<>();
541 if (cloudSiteId != null && cloudSiteId.equals(TESTING_KEYWORD)) {
542 if (tenantId != null && tenantId.equals(TESTING_KEYWORD)) {
543 throw new VnfException("testing.");
545 vnfExists.value = true;
546 vfModuleId.value = TESTING_KEYWORD;
547 status.value = VnfStatus.ACTIVE;
548 outputs.value = testMap();
550 vnfAdapter.queryVnf(cloudSiteId, tenantId, volumeGroupStackId, msoRequest, vnfExists, vfModuleId, status, outputs);
552 if (!vnfExists.value) {
553 LOGGER.debug ("VNFVolumes not found");
554 qryResp.setVolumeGroupStatus(status.value);
555 respStatus = HttpStatus.SC_NOT_FOUND;
557 LOGGER.debug ("VNFVolumes found " + vfModuleId.value + ", status=" + status.value);
558 qryResp.setVolumeGroupStatus(status.value);
559 qryResp.setVolumeGroupOutputs(outputs.value);
561 LOGGER.debug("Query queryVNFVolumes exit");
564 .entity(new GenericEntity<QueryVolumeGroupResponse>(qryResp) {})
566 } catch (VnfException e) {
567 LOGGER.error(MessageEnum.RA_QUERY_VNF_ERR, aaiVolumeGroupId, "", "queryVNFVolumes", MsoLogger.ErrorCode.BusinessProcesssError, "VnfException - queryVNFVolumes", e);
568 VolumeGroupExceptionResponse excResp = new VolumeGroupExceptionResponse(e.getMessage(), MsoExceptionCategory.INTERNAL, Boolean.FALSE, null);
569 LOGGER.debug("Query queryVNFVolumes exit");
571 .status(HttpStatus.SC_INTERNAL_SERVER_ERROR)
572 .entity(new GenericEntity<VolumeGroupExceptionResponse>(excResp) {})
576 public static Map<String, String> testMap() {
577 Map<String, String> m = new HashMap<>();
578 m.put("mickey", "7");
579 m.put("clyde", "10");
580 m.put("wayne", "99");